这道题目我一定要好好吐槽一下,二维char数组表示成一维string,用来表示状态,然后求sg函数值用记忆化搜索,然后就一直WA,心好累差点怀疑人生,QAQ。后来发现记忆化搜索代码加上 if(vis[str])return sg[str]; 就WA,所以肯定这里出问题,后来一想,这种状态表示有毒,例如5x4与4x5的矩阵显然不同,但是展开成一维string时显然可以得到相同string,所以二维展一维时除了内容,还要加上R,C两个参数。可是这样就要用结构体,想想acm中处理字符串的技巧,其实在二维数组表示成string时,在末尾加上一个区别的符号就行了。这样就可以写最正宗的记忆化搜索了。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <cstring>
using namespace std;
char g[55][55];
map<string,int>sg;
map<string,int>vis;
string ss;
int R,C;
string tostr(){
ss="";
for(int i=0;i<R;i++){
ss+=g[i];
ss+='*';
}
return ss;
}
int grundy(){
string str=tostr();//cout<<str<<endl;
if(vis[str])return sg[str];
int s[100];
memset(s,0,sizeof(s));
for(int i=1;i<R;i++){
for(int j=1;j<C;j++){
if(g[i][j]=='0'&&g[i-1][j]=='0'&&g[i][j-1]=='0'&&g[i-1][j-1]=='0'){
g[i][j]='1';g[i-1][j]='1';g[i][j-1]='1';g[i-1][j-1]='1';
s[grundy()]=1;
g[i][j]='0';g[i-1][j]='0';g[i][j-1]='0';g[i-1][j-1]='0';
}
}
}
int k=0;
while(s[k])k++;
vis[str]=1;
sg[str]=k;
return k;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF){
int ans=0;
for(int i=0;i<n;i++){
scanf("%d%d",&R,&C);
for(int j=0;j<R;j++)scanf("%s",g[j]);
ans^=grundy();
}
printf("%s\n",ans?"Yes":"No");
}
return 0;
}