• toj 1017. Number Game 夜


    http://202.113.2.5:57778/toj/showp1017.html

    DP (状态压缩+记忆化搜索) + 博弈论

    基本思路:

    用状态压缩表示 那些是还可以选的 哪些是不可以选的

    在更新过程中 标记 是否是奇异状态

    代码及其注释:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<vector>
    #include<queue>
    #include<map>
    #include<stack>
    #include<algorithm>
    
    using namespace std;
    //#pragma comment(linker,"/STACK:1000000000,1000000000")
    
    #define LL long long
    
    const int INF=0x3f3f3f3f;
    const int M=20;
    const int N=(1<<M)-1;
    int fail[N+10];//0 为初始化 1 表示奇异状态 -1 表示非奇异状态
    bool can[25];//标记
    int Fnext(int x,int l)//在x状态下 选择数字 l+1 (既用位运算表示左移 l 位) 时得到新的状态
    {
        int temp=x;
        temp=temp|(1<<l);
        for(int i=1;i<M;++i)
        {
            if((temp&(1<<i))&&(i+l+1)<20)
            {
                temp=temp|(1<<(i+l+1));
            }
        }
        return temp;
    }
    int dp(int x)//求是否是奇异状态
    {
        if(fail[x]!=0)
        return fail[x];
        if(x==N)
        {
            fail[x]=1;
            return fail[x];
        }
        for(int l=1;l<M;++l)
        {
            if((x&(1<<l)))
            continue;
            int temp=Fnext(x,l);
            if(dp(temp)==1)//有任一个可能更新到奇异状态 则当前状态为非奇异状态
            fail[x]=-1;
        }
        if(fail[x]==0)//否则为奇异状态
        fail[x]=1;
        return fail[x];
    }
    int main()
    {
        //freopen("data.txt","r",stdin);
        memset(fail,0,sizeof(fail));
        int T;
        scanf("%d",&T);
        for(int ca=1;ca<=T;++ca)
        {
            int n;
            scanf("%d",&n);
            memset(can,false,sizeof(can));
            while(n--)
            {
                int temp;
                scanf("%d",&temp);
                if(temp<=20&&temp>1)
                can[--temp]=true;
            }
            int k=0;
            for(int i=1;i<M;++i)
            {
                if(can[i]==false)
                k=Fnext(k,i);
            }
            printf("Scenario #%d:\n",ca);
            if(dp(k)==1)//当前为奇异状态
            {
                printf("There is no winning move");
            }else
            {
                printf("The winning moves are:");
                for(int l=1;l<M;++l)
                {
                    if((k&(1<<l)))
                    continue;
                    int temp=Fnext(k,l);//非奇异状态的话 看有哪几个选择
                    if(dp(temp)==1)
                    printf(" %d",l+1);
                }
            }
            printf(".\n\n");
        }
        return 0;
    }
    
  • 相关阅读:
    [CSP-S模拟测试]:赛(贪心+三分)
    [CSP-S模拟测试]:联(小清新线段树)
    [CSP-S模拟测试]:z(模拟+map+小根堆)
    赛瓦维斯特定理
    [CSP-S模拟测试]:y(DP+bitset)
    [CSP-S模拟测试]:x(数学+并查集)
    [杂题]:staGame(博弈论+Trie树+DFS)
    [杂题]:group(状压DP+轮廓线)
    [CSP-S模拟测试]:w(树上DP)
    BZOJ4103 [Thu Summer Camp 2015]异或运算 【可持久化trie树】
  • 原文地址:https://www.cnblogs.com/liulangye/p/2717316.html
Copyright © 2020-2023  润新知