bzoj:1457: 棋盘游戏
原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1457
看了网上dalao的题解,好像解释得并不是很清楚,就按照那种思路,自己YY了一个想法,写出来居然跟std是一样的。
首先如果刚开始棋盘上有X=0或Y=0或X==Y先特判掉。
如果我们把走到(0,0)对应于将一堆石子取空,那么剩下的难点在于一般的Nim游戏是所有石子堆均被取空则游戏结束,而这里只要一堆空就结束了,这很气……
那么我们需要考虑转换一下一堆石子被取空时对应的情景。
如果有人走到X=0或Y=0或X==Y,对手即刻就胜利了,最优策略里谁都不会这么走,也就是说,走到X=0或Y=0或X==Y这种情况是不被允许的。要是有人实在没办法走别的地方,必须走这里,他就输了。这里就转化为不允许走到X=0或Y=0或X==Y,谁无法在这一限制内继续行动,就是失败者。
这样一来就是正常的Nim题了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #define MN 1000 using namespace std; int read_p,read_ca; inline int read(){ read_p=0;read_ca=getchar(); while(read_ca<'0'||read_ca>'9') read_ca=getchar(); while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar(); return read_p; } int T,n,m,a,b,mmh,MMH,sg[100][100]; bool bo[1001]; int main(){ register int i,j; for (i=1;i<100;i++) for (j=1;j<100;j++) if (i!=j){ memset(bo,0,sizeof(bo)); for (int k=1;k<i&&k<j;k++) bo[sg[i-k][j-k]]=1; for (int k=1;k<i;k++) if (i-k!=j) bo[sg[i-k][j]]=1; for (int k=1;k<j;k++) if (i!=j-k) bo[sg[i][j-k]]=1; for (int k=0;;k++) if (!bo[k]){sg[i][j]=k;break;} } T=read(); while (T--){ n=read();mmh=MMH=0; while (n--){ a=read();b=read(); if (a==0&&b==0) MMH|=2; if (a==0||b==0||a==b) MMH|=1;else mmh^=sg[a][b]; } if (MMH) puts(MMH==1?"^o^":"T_T");else puts(mmh?"^o^":"T_T"); } }
YY成功真开心。