hdu 1536(博弈)

传送门:S-Nim

题意:给n个数的集合s, 再给m 组数据,每组表示 k 堆石子,每次可以取的个数只能是集合s中的数量。问先手胜还是输?

分析:sg函数的经典运用,先预处理出所有数量为0~10000的石子的sg值,然后判断k堆石子的sg值异或和是否为0来判断先手的输赢。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 110
using namespace std;
int n,m,k;
int sg[N*N],a[N];
int dfs(int x)
{
    if(~sg[x])return sg[x];
    int vis[N],temp;
    memset(vis,0,sizeof(vis));
    for(int i=0;i<n;i++)
    {
        int temp=x-a[i];
        if(temp<0)break;
        temp=dfs(temp);
        vis[temp]=1;
    }
    for(int i=0;;i++)
    {
        if(vis[i])continue;
        return sg[x]=i;
    }

}
int main()
{
    while(scanf("%d",&n),n)
    {
        memset(sg,-1,sizeof(sg));
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
        }
        sort(a,a+n);
        for(int i=0;i<=10000;i++)
            if(sg[i]==-1)dfs(i);
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d",&k);
            int x,ans=0;
            for(int i=0;i<k;i++)
            {
                scanf("%d",&x);
                ans^=sg[x];
            }
            if(ans)printf("W");
            else printf("L");
            if(!m)puts("");
        }

    }
}
View Code
原文地址:https://www.cnblogs.com/lienus/p/4326803.html