S-Nim HDU 1536 博弈 sg函数

时间:2019-10-19
本文章向大家介绍S-Nim HDU 1536 博弈 sg函数,主要包括S-Nim HDU 1536 博弈 sg函数使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

S-Nim HDU 1536 博弈 sg函数

题意

首先输入K,表示一个集合的大小,之后输入集合,表示对于这对石子只能去这个集合中的元素的个数,之后输入 一个m表示接下来对于这个集合要进行m次询问,之后m行,每行输入一个n表示有n个堆,每堆有n1个石子,问这一行所表示的状态是赢还是输,如果赢输入W否则L。

解题思路

如果没有每次取石子个数的限制的话,那么仅仅需要把每堆石子的个数进行异或运算即可,如果结果不是1,那么先手赢,反之后手赢。

但是这里对每次取石子的个数进行了限制,每次只能从几个数中进行选择,这是就需要SG函数来进行处理了。至于为什么要使用SG函数来进行处理这里没有写,详细可以参考这个博客博弈论 SG函数

这里仅仅写了SG函数的两种写法:1是打表法,2是DFS法。

代码实现

//打表法实现
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e4+7;
int sg[maxn];
bool book[maxn];//这个需要用bool类型,如果改成int类型会超时,第一次遇到。
int s[107];
int k, m, l;
void getsg(int n, int k)//n代表这堆石子最多有多少,k代表有多少种取的模式
{
    int i, j;
    memset(sg, 0, sizeof(sg));
    for(i=1; i<=n; i++)
    {
        memset(book, 0, sizeof(book));//每次有需要进行
        for(j=1; j<=k && s[j]<=i; j++)
            book[sg[i-s[j]]]=1;
        for(j=0; ; j++)//查找里面第一个是0的
            if(!book[j])
            {
                sg[i]=j;
                break;
            }
    }
}
int main()
{
    while(scanf("%d",&k) && k)
    {
        for(int i=1; i<=k; i++)
            scanf("%d",&s[i]);
        sort(s+1, s+1+k);
        getsg(maxn-7, k);
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d", &l);
            int tmp, ans=0;
            while(l--)
            {
                scanf("%d", &tmp);
                ans^=sg[tmp];
            }
            if(ans==0)
                printf("L");
            else
                printf("W"); 
        }
        printf("\n");
    }
    return 0;
}
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=10050+7;
int s[105];
int SG[maxn];
bool book[105];
int k, m, l;
int sg(int x)
{
    if(SG[x]!=-1) return SG[x];//记忆化搜索
    memset(book, 0, sizeof(book));
    for(int i=1; i<=k && x-s[i]>=0; i++)
        book[sg(x-s[i])]=1; //寻找他的下面的所有状态
    for(int i=0; i<105; i++) //找到第一个是0的位置
        if(book[i]==0) return SG[x]=i;
}

int main()
{
    while(scanf("%d", &k) && k)
    {
        for(int i=1; i<=k; i++)
            scanf("%d", &s[i]);
        sort(s+1, s+1+k);
        memset(SG, -1, sizeof(SG));
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d", &l);
            int tmp, ans=0;
            for(int i=1;i<=l; i++)
            {
                scanf("%d", &tmp);
                ans^=sg(tmp);
            }
            if(ans==0) printf("L");
            else printf("W");
        }
        printf("\n");
    }
    return 0;
 } 

原文地址:https://www.cnblogs.com/alking1001/p/11704461.html