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;
}

 

posted @ 2018-08-02 10:50  Zinn  阅读(192)  评论(0编辑  收藏  举报