[51nod1329]路径游戏
Snuke与Sothe两个人在玩一个游戏。游戏在一个2*N的网格中进行(2行N列),这个网格中的2N个格子不是黑色就是白色。定义,一条有效路径是指一个完全由白色格子构成的序列,这个序列的第一个网格元素是最左端两个网格之一,最后一个元素是最右端两个网格之一,且在序列中任意两个连续元素在网格中是边相邻的。(任意一个格子与其上下左右四个方向上的网格边相邻,当然在2*N网格中,一个格子只有最多3个相邻的格子。)游戏初始时确保这个网格中存在至少一条有效路径。游戏开始后Snuke与Sothe轮流进行操作,每一次操作需要选择网格中的一个白格并将其涂黑,且操作后的网格中必须依然存在至少一条有效路径。若一个人操作完后网格中不再存在有效路径的话,该操作选手判为输,而另一个选手为赢。假设Snuke与Sothe两人都采用最优策略,且Snuke先手。那么请问对给定的初始网格涂色状态,谁是最终的赢家?
例如,初始状态如下:('.'表示白色,‘#’表示黑色)
#..
...
Snuke必须先手把右下角涂黑,
#..
..#
而此时Sothe将无路可走。
Input
多组测试数据。
第一行一个整数T,表示数据个数,其中1<=T<=5。
接下来3T行,是T组不同的数据。
每组数据由3行构成,其第一行是一个整数N,其中1<=N<=1000
接下来两行每行N个字符,表示网格中每个格子的初始颜色,'.'表示白色,‘#’表示黑色。
Output
每组数据一行输出,输出获胜玩家名字。
直接求SG函数。。sg[i][ztl][ztr]表示中间2*i个全空的格子,再往左右那两列有无障碍格子的状态分别为ztl,ztr 的SG值。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<cmath> 7 #include<cstdlib> 8 #define ll long long 9 #define ull unsigned long long 10 #define ui unsigned int 11 #define d double 12 #define ld long double 13 const int maxn=2333,modd=1000000007; 14 15 int sg[1012][4][4]; 16 int u[23333]; 17 char s1[maxn],s2[maxn]; 18 int i,j,k,n,m; 19 20 int ra,fh;char rx; 21 inline int read(){ 22 rx=getchar(),ra=0,fh=1; 23 while(rx<'0'&&rx!='-')rx=getchar(); 24 if(rx=='-')fh=-1,rx=getchar(); 25 while(rx>='0')ra=ra*10+rx-48,rx=getchar();return ra*fh; 26 } 27 28 inline void getsg(){ 29 int i,ztl,ztr,tim=0;register int j; 30 for(i=0;i<=1000;i++)for(ztl=3;ztl>=0;ztl--)for(ztr=3;ztr>=0;ztr--) 31 if((i>0&&ztl!=3&&ztr!=3)||(!i&&((ztl|ztr)!=3))){ 32 tim++; 33 for(j=0;j<i;j++){ 34 if((j>0&&j<i-1)|| ((j||!(ztl&2))&&(j<i-1||!(ztr&2))) )u[sg[j][ztl][1]^sg[i-j-1][1][ztr]]=tim; 35 if((j>0&&j<i-1)|| ((j||!(ztl&1))&&(j<i-1||!(ztr&1))) )u[sg[j][ztl][2]^sg[i-j-1][2][ztr]]=tim; 36 }//printf("trying: %d %d %d\n",i,ztl,ztr); 37 if(!ztl&&(i>0||!(ztr&2)))u[sg[i][1][ztr]]=tim; 38 if(!ztl&&(i>0||!(ztr&1)))u[sg[i][2][ztr]]=tim; 39 if(!ztr&&(i>0||!(ztl&2)))u[sg[i][ztl][1]]=tim; 40 if(!ztr&&(i>0||!(ztl&1)))u[sg[i][ztl][2]]=tim; 41 42 for(j=0;u[j]==tim;j++);sg[i][ztl][ztr]=j;//if(i<3)printf(" SG:%d %d %d %d\n",i,ztl,ztr,j); 43 }else sg[i][ztl][ztr]=233333; 44 } 45 46 int main(){ 47 getsg(); 48 for(int T=read();T;T--){ 49 int len=0,SG=0; 50 m=read(); 51 scanf("%s%s",s1+1,s2+1); 52 if(m==1)SG=(s1[1]=='.'&&s2[1]=='.')?1:0; 53 for(i=2;i<=m;i++) 54 if(s1[i]=='.'&&s2[i]=='.'&&i<m)len++; 55 else{ 56 int ztl=(s1[i-len-1]=='#')<<1|(s2[i-len-1]=='#'),ztr=(s1[i]=='#')<<1|(s2[i]=='#'); 57 // printf("SG:%d %d %d %d\n",len,ztl,ztr,sg[len][ztl][ztr]); 58 SG^=sg[len][ztl][ztr],len=0; 59 } 60 puts(SG?"Snuke":"Sothe"); 61 } 62 }