题意:
一个n行20列的棋盘。 每一行有若干个棋子。 两人轮流操作, 每人每次可以将一个棋子向右移动一个位置, 如果它右边有一个棋子, 就跳过这个棋子, 如果有若干个棋子, 就将这若干个都跳过。 但是棋子不能移出边界。 如果没有办法移动了, 就算输。 问你先走的能否赢。分析: 使用状压的SG. 把每一列的答案异或起来.
1 #include2 #include 3 #include 4 using namespace std; 5 const int SIZE = 1<<21; 6 int SG[SIZE]; 7 int t, n, m; 8 int GetSG(int x) 9 {10 if(SG[x] != -1) return SG[x];11 int vis[50]={ 0},nxt=-1;12 for(int i = 0; i < 20; i++)13 {14 if((x&(1 << i)) == 0) nxt=i;//离棋子最近的空格 15 else if(nxt != -1) {16 vis[GetSG(x ^ (1< << (20 - x);//左右互换,走到20变为走到 1 46 }47 ans ^= SG[p];//所有答案异或 48 }49 if(ans) puts("YES");50 else puts("NO");51 }52 return 0;53 }