首先先写一波题面吧:题意:给定一个棋盘,左上角为(0,0),棋盘中有多个骑士,每一个骑士只能按照图中的6种方式移动,两个人轮流移动棋盘中任意一个骑士,当轮到某一个人移动骑士时,棋盘中的骑士都已经不能移动了则判定为输,Alice先移动棋盘中的骑士,最后输出Alice和Bob谁赢谁输。
这道题可以说是一眼题了,只要看到这样就可以想到是递推的,然后的话便可以用sg函数打表来做,但是一个重要的问题就是如果用递推打表的话,有一个状态是还没有访问到的,这样不符合dag的顺序,所以不能递推打表,所以只能用记忆化搜索的方法来写
然后就是用记忆化搜索来写,打出子函数的值后异或一下就好了但是接下来就有一个很重要的问题,也是我一直死t的原因,我的数组开了全居,当进入下一次循环的时候,我置0了一次,但是又回溯回来后以前的值改了,导致这样打出来的sg值不对,然后一直死循环
下面先是错误的代码:
1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<iostream> 5 #include<set> 6 using namespace std; 7 const int maxn=1100; 8 int sg[maxn][maxn]; 9 int fx[6][2] = {{1, -2}, {-1, -3}, {-1, -2}, {-2, -1}, {-3, -1}, {-2, 1}}; 10 int vis[11]; 11 int t,n,a,b; 12 13 //这可以扯到变量生存周期的那方面的东西 14 int get_sg(int x,int y){ 15 if(sg[x][y]!=-1) return sg[x][y]; 16 memset(vis,0,sizeof(vis));//注意这个数组不能开全局 17 for(int k=0;k<6;k++){ //下一次回溯回来的时候会对这个有影响 18 int xx=x+fx[k][0];//你可能打出来的sg函数的值 19 int yy=y+fx[k][1];//在进入下一个循环的时候置0, 20 if(xx>=0&&yy>=0){//回溯回来后原先的值就全变了 21 vis[get_sg(xx,yy)]=1; 22 } 23 } 24 int e; 25 for(int i=0;;i++){ 26 if(!vis[i]){ 27 e=i; 28 break; 29 } 30 } 31 return sg[x][y]=e; 32 } 33 34 int main(){ 35 memset(sg,-1,sizeof(sg)); 36 scanf("%d",&t); 37 for(int kase=1;kase<=t;kase++){ 38 scanf("%d",&n); 39 int ans=0; 40 for(int i=1;i<=n;i++){ 41 scanf("%d%d",&a,&b); 42 ans^=get_sg(a,b); 43 } 44 printf("Case %d: ",kase); 45 if(ans) printf("Alice\n"); 46 else printf("Bob\n"); 47 } 48 return 0; 49 }
下面是正确的代码
1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<iostream> 5 #include<set> 6 using namespace std; 7 const int maxn=1100; 8 int sg[maxn][maxn]; 9 int fx[6][2] = {{1, -2}, {-1, -3}, {-1, -2}, {-2, -1}, {-3, -1}, {-2, 1}}; 10 int t,n,a,b; 11 12 13 int get_sg(int x,int y){ 14 if(sg[x][y]!=-1) return sg[x][y]; 15 int vis[11]; 16 memset(vis,0,sizeof(vis)); 17 for(int k=0;k<6;k++){ 18 int xx=x+fx[k][0]; 19 int yy=y+fx[k][1]; 20 if(xx>=0&&yy>=0){ 21 vis[get_sg(xx,yy)]=1; 22 } 23 } 24 int e; 25 for(int i=0;;i++){ 26 if(!vis[i]){ 27 e=i; 28 break; 29 } 30 } 31 return sg[x][y]=e; 32 } 33 34 int main(){ 35 memset(sg,-1,sizeof(sg)); 36 scanf("%d",&t); 37 for(int kase=1;kase<=t;kase++){ 38 scanf("%d",&n); 39 int ans=0; 40 for(int i=1;i<=n;i++){ 41 scanf("%d%d",&a,&b); 42 ans^=get_sg(a,b); 43 } 44 printf("Case %d: ",kase); 45 if(ans) printf("Alice\n"); 46 else printf("Bob\n"); 47 } 48 return 0; 49 }