相对简单的SG博弈
可以参见 http://blog.csdn.net/solotzg/article/details/8979406
题目中明确表示一个格子无法被两个空格同时影响,所以全局的状态可以划分为两类:
sg(a): 单个包含数字的格子
sg(b):空格及其所能影响的区域
在这两类中状态的转移是互不影响的。
sg(a) == 1;恒成立
sg(b)中,若该区域含有b个数字格子,则通过状态转移并寻找规律发现sg(0) == 1; sg(1) == 2;sg(2) == 1......
即 sg(b) = (b&1)+1;
res =sg(a1)^sg(a2)^sg(a3)^…^sg(an) ^ sg(b1)^sg(b2)^sg(b3)^…^sg(bm)
n为单个数字格子的个数;m为空格及其所能影响的区域的个数
#include<cstdio> #include<algorithm> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int MAXN = 1005; int mmp[MAXN][MAXN], vis[MAXN][MAXN]; const int dir[8][2] = { 1,0, -1,0, 0,1, 0,-1, -1,-1, -1,1, 1,-1, 1,1 }; int getSG(int a) { return (a&1)+1; } int n, m, k, cnt; void dfs(int x, int y) { vis[x][y] = 1; for (int i = 0; i< 8; ++i) { int xx = x+dir[i][0], yy = y+dir[i][1]; if (xx >= 0 && xx < n && yy >=0 && yy<m && !vis[xx][yy]) { if (mmp[xx][yy]) ++cnt, vis[xx][yy] = 1; else dfs(xx, yy); } } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int t; scanf("%d", &t); for (int o = 1; o<= t; ++o) { printf("Case #%d: ", o); int res = 0; memset(mmp, 0, sizeof mmp); memset(vis, 0, sizeof vis); scanf("%d%d%d", &n, &m, &k); for (int i = 0; i< k; ++i) { int x, y; scanf("%d%d", &x, &y); vis[x][y] = 1; for (int j = 0; j< 8; ++j) { int xx = x+dir[j][0], yy = y+dir[j][1]; if (xx >= 0 && xx < n && yy >=0 && yy<m) ++mmp[xx][yy]; } } for (int i = 0; i< n; ++i) { for (int j = 0; j< m; ++j) { if (vis[i][j] || mmp[i][j]) continue; cnt = 0; dfs(i, j); res ^= getSG(cnt); } } for (int i = 0; i< n; ++i) { for (int j = 0; j< m; ++j) { if (!vis[i][j]) res ^= 1; } } if (res) puts("Xiemao"); else puts("Fanglaoshi"); } return 0; }