题目:题目链接
题意:题目意思就是两人玩扫雷,按照变换的规则。如果点着空地那么周围不包含数字的空地都会被触发。这样:把点
开空地时会打开的一大片区域看成一块,题目中说到,在一盘游戏中,一个格子不可能被翻开两次,说明任意两块空地
不会包含相同的格子。那么就可以看成一个组合游戏。当空地旁边没连任何数字的时候,sg = 1(直接转移到0)。如果
有一个数字,点空地可以转移到0,点数字可以转移到1,所以sg = 2。有2 个数字点空地转移到0,点数字转移到2,所
以sg = 1。以此类推,空地旁边有奇数个数字的时候,sg = 2,否则sg = 1。剩下的没与空地相连的数字,每个的sg
都是1。那么将所有空地的sg 异或起来,再异或(不与空地相连的数字个数对2取模),等于零输出后手赢,大于0 输出
先手赢即可。
我们根据题目的数据,初始化0,有雷的标记,比如3,那么雷周围就标记为数字1.这样,我们找到一个空地0,如果这
个空地未被访问,那么就DFS一次,查找它所连接的数字的个数,并把记录过的数字标记。这样避免重复。最后,我们
在统计剩余的没有和空地相连的数字的个数,按照SG值取,最后看ans的情况就可以了:
#include <iostream> #include <cstdio> #include <string> #include <string.h> #include <vector> #include <cstdlib> #include <algorithm> #include <cmath> #include <queue> #include <set> #include <stack> #include <functional> #include <fstream> #include <sstream> #include <iomanip> #include <numeric> #include <cassert> #include <bitset> #include <stack> #include <ctime> #include <list> #define INF 0x7fffffff #define max3(a,b,c) (max(a,b)>c?max(a,b):c) #define min3(a,b,c) (min(a,b)<c?min(a,b):c) #define mem(a,b) memset(a,b,sizeof(a)) #pragma comment(linker,"/STACk:1024000000,1024000000") using namespace std; int map[1100][1100]; int f[8][2]= {{0,1},{0,-1},{-1,1},{-1,0},{-1,-1},{1,-1},{1,0},{1,1}}; int n,m; int tmp; int dfs(int i,int j) { map[i][j] = 3; for(int k=0; k<8; k++) { int x = i + f[k][0]; int y = j + f[k][1]; if(x>=0&&y>=0&&x<m&&y<n) { if(map[x][y]==1)//数数字的个数 { map[x][y] = 2;//标记已被取过 tmp++; } else if(!map[x][y]) dfs(x,y); } } return 0; } int main() { int T, index; int ki; int i, j; int xi, yi; scanf("%d", &T); for(index = 1; index <= T; index++) { memset(map, 0, sizeof(map)); int ans = 0; scanf("%d%d%d", &m, &n, &ki); for(i = 0; i < ki; i++) { scanf("%d%d", &xi, &yi); map[xi][yi] = 3;//有雷布置 for(int k = 0; k < 8; k++) { int x=xi+f[k][0]; int y=yi+f[k][1]; if(x>=0&&y>=0&&x<m&&y<n) { if(!map[x][y]) map[x][y]=1;//和雷相连置数字 } } } for(i=0; i<m; i++) { for(j=0; j<n; j++) if(!map[i][j])//空地 { tmp=0; dfs(i,j); if(tmp&1) ans^=2; else ans^=1; } } int ans1=0; for(i=0; i<m; i++) { for(j=0; j<n; j++) { if(map[i][j]==1)//求不与空地相连的数字 ans1++; } } ans1 %= 2; ans ^= ans1; printf("Case #%d: ",index); if(ans) printf("Xiemao\n"); else printf("Fanglaoshi\n"); } return 0; }