[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
",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
",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
",len,ztl,ztr,sg[len][ztl][ztr]);
58                 SG^=sg[len][ztl][ztr],len=0;
59             }
60         puts(SG?"Snuke":"Sothe");
61     }
62 }
View Code
原文地址:https://www.cnblogs.com/czllgzmzl/p/5950978.html