bzoj 3895 取石子 —— 博弈论
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3895
看了博客:https://blog.csdn.net/popoqqq/article/details/43989101
因为只是找有无必胜策略,所以可以搜索求解;
注意记忆化数组不必清空,因为同种状态对应的答案都一样。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int const maxm=50005; int T,n,a[55],f[55][maxm]; bool v[55][maxm]; bool dfs(int x,int y) { if(v[x][y])return f[x][y]; v[x][y]=1; if(!x)return f[x][y]=(y&1);// if(y==1)return f[x][y]=dfs(x+1,0);//既然v[x][y]=1,则必须赋f[x][y] if(x&&!dfs(x-1,y))return f[x][y]=1; if(x>1&&!dfs(x-2,y+2+(y!=0)))return f[x][y]=1; if(y&&!dfs(x,y-1))return f[x][y]=1;// if(x&&y&&!dfs(x-1,y+1))return f[x][y]=1;//&&y return f[x][y]=0; } int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); int cnt=0,st=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); if(a[i]>1)cnt++,st+=a[i]; } st+=cnt-1; cnt=n-cnt; if(st==-1)st=0;//!!! // memset(v,0,sizeof v);//不必清空!!! if(dfs(cnt,st))printf("YES\n"); else printf("NO\n"); } return 0; }