初接触sg函数 hdoj3980

第一次打关于sg函数的题目,发现是真得有点难,同时运用到dfs和位运算符来表示它后继的状态数

需要注意

sg(i)=mex(sg(i的后继))

mex()集合没出现过的最小自然数

一、sg函数是求一个状态的后继,sg(i)=0,证明这个状态是一个必败态,无论什么操作一定是输

二、如果sg(i)!=0,当前状态必胜,因为可以必然进入后继sg值为零的点所以必胜

三、vis表示是一个上一个状态能到达的标记,把x细分为i和x-m-i两部分,然后对其进行赋值,详细需要自己去理解

,每一题需要自己去积累

#include <iostream>
#include <cstdio>
using namespace std;
int n,m;
int sg[2005];

int dfs(int x)
{
    if(x<m)return sg[x]=0;
    if(sg[x]!=-1) return sg[x];
    bool vis[2005]= {false};
    for(int i=0; i<=x-m; i++)
    {
        vis[dfs(i)^dfs(x-m-i)]=1;
    }
    for(int i=0;; i++)
    {
        if(!vis[i])
        {
            sg[x]=i;
            break;
        }
    }
    return sg[x];
}
int main()
{
    int t;
    cin>>t;
    int cou=1;
    while(t--)
    {
        cin>>n>>m;

        for(int i=0; i<2000; i++)
            sg[i]=-1;
        sg[0]=0;
        printf("Case #%d: ",cou++);

        if(n<m)
        {
            printf("abcdxyzk\n");
            continue;
        }
        if(dfs(n-m)) printf("abcdxyzk\n");
        else
           printf("aekdycoin\n");

    }
}

猜你喜欢

转载自blog.csdn.net/qq_42193011/article/details/80956271