http://acm.hdu.edu.cn/showproblem.php?pid=1536

S-Nim 博弈 需要用SG 处理

最简单的S-Nim博弈是 每一堆可以任取正整数个 比如说 k 可以变成 k-1,k-2,k-3,······0

本题所可以取的数量有了限制 所以要SG处理 把原始数量可以对应到 S-Nim 里面的数量 是多对一的关系

如果原始数量n取过之后可以变成 S-Nim 里面的0,1,2,3,4,····· k-1 而没有 k 的话 那么n就对应到 S-Nim里面的 k

然后就变成最初的S-Nim了

代码:

#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 N=105;
const int M=10005;
int choose[N];
int k[M];
int n;
int dp(int x)
{
    if(k[x]!=-1)
    return k[x];
    int visited[N];
    memset(visited,false,sizeof(visited));
    for(int i=0;i<n;++i)
    {
        if(x-choose[i]<0)
        break;
        visited[dp(x-choose[i])]=true;
    }
    for(int i=0;i<=n;++i)
    if(visited[i]==false)
    {k[x]=i;break;}
    return k[x];
}
int main()
{
    //freopen("data.txt","r",stdin);

    while(scanf("%d",&n)!=EOF,n)
    {
        for(int i=0;i<n;++i)
        scanf("%d",&choose[i]);
        sort(choose,choose+n);
        memset(k,-1,sizeof(k));
        int m;
        scanf("%d",&m);
        while(m--)
        {
            int l;
            scanf("%d",&l);
            int w=0;
            while(l--)
            {
                int tmp;
                scanf("%d",&tmp);
                w=(w^dp(tmp));
            }
            if(w)
            printf("W");
            else
            printf("L");
        }
        printf("\n");
    }
    return 0;
}

 

 

posted on 2012-10-15 22:04  夜->  阅读(190)  评论(0编辑  收藏  举报