HDU 4678
把点开空地时会打开的一大片区域看成一块,题目中说到,在一盘游戏
中,一个格子不可能被翻开两次,说明任意两块空地不会包含相同的格子。
那么就可以看成一个组合游戏。
当空地旁边没连任何数字的时候,sg = 1(直接转移到 0)。如果有一个
数字,点空地可以转移到 0,点数字可以转移到 1,所以 sg = 2。有 2 个数
字点空地转移到 0,点数字转移到 2,所以 sg = 1。
以此类推,空地旁边有奇数个数字的时候,sg = 2,否则 sg = 1。
剩下的没与空地相连的数字,每个的 sg 都是 1。
那么将所有空地的 sg 异或起来,再异或 (不与空地相连的数字个数对 2
取模),等于零输出后手赢,大于 0 输出先手赢即可。
#include<stdio.h> #include<string.h> #pragma comment(linker,"/STACk:1024000000,1024000000") int map[1100][1100]; //bool flag[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; } void myprintf() { for(int i=0;i<m;i++) { for(int j=0;j<n;j++) printf("%d ",map[i][j]); printf(" "); } } int main() { int _case,ij; int ki,i,j,xi,yi; scanf("%d",&_case); for(ij=1; ij<=_case; ij++) { 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); //printf("##%d ",tmp); if(tmp&1)ans^=2; else ans^=1; } } int ans1=0; //int ans2=0; //myprintf(); 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: ",ij); if(ans)printf("Xiemao "); else printf("Fanglaoshi "); } return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* //求sg函数值代码如下 #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; #define maxn 1111 int sg[maxn];//sg[i]表示由一个空白区域加上i-1个边缘数字区的sg值 int vis[maxn]; void init() { int i,j,k; sg[0]=0; sg[1]=1; for(i=2;i<1000;i++) { memset(vis,0,sizeof(vis)); vis[sg[i-1]]=1; //点击数字区域 vis[0]=1; //点击空白区域,后继状态必败 for(j=0;;j++) if(vis[j]==0) { sg[i]=j; break; } } for(i=0;i<20;i++) cout<<sg[i]<<" "; cout<<endl; } int main() { init(); return 0; } //SG值:0 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 */