poj2960(SG函数)

本文介绍了一种使用SG函数解决博弈论中石头游戏的方法。通过计算不同状态下SG值,利用异或运算判断游戏结果,帮助理解SG函数在解决此类问题中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给n堆石头,每堆有hi个,玩家轮流选一堆石头取走x个,x属于集合S;

用sg函数来解,如果对sg函数理解的话,做这题就不会有问题。

代码如下:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<time.h>
#include<math.h>

#define inf 0x7fffffff
#define eps 1e-9
#define pi acos(-1.0)
#define P system("pause")
using namespace std;
#define N 10000+5
int s[100+5],sg[N],vis[N];
void get_sg(int n)//求sg数组
{
    memset(sg,0,sizeof(sg));
    int i, j;
    for(i = 0; i < s[0]; i++)
        sg[i] = 0;
    for(; i <= 10000; i++)//求状态i的sg值
    {
        memset(vis,0,sizeof(vis));
        for(j = 0; j < n; j++)//遍历状态i的后继状态
            if(i - s[j] >= 0)
                vis[sg[i-s[j]]] = 1;
            else break;
        for(j = 0; ; j++)//求后继状态的sg中不存在的最小非负整数
            if(!vis[j]){
                sg[i] = j;
                break;
            }
    }
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
    int sn;
    while(scanf("%d",&sn) && sn)
    {
        int i;
        for(i = 0 ; i < sn; i++)
            scanf("%d",&s[i]);
        sort(s,s+sn);
        get_sg(sn);
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n,res = 0;
            scanf("%d",&n);
            while(n--)
            {
                int k;
                scanf("%d",&k);
                res ^= sg[k];//sg定理:游戏的结果是其子游戏结果的异或和
            }
            if(!res) printf("L");//结果为0,是必败状态
            else printf("W");
        }
        printf("\n");


    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值