UVA 1378 A Funny Stone Game (经典博弈)

来源:互联网 发布:mac 最好的五笔输入法 编辑:程序博客网 时间:2024/05/21 14:59

题目传送门


代码不是关键,关键的是对博弈和sg函数的理解。重点是在构造sg函数的时候是将一个石头看成一个堆,所以按照sg函数的定义后继状态为两个石头构成的堆。然后根据对称性原理和xor的性质,在某个堆,只有石头个数为奇数时才会对参与xor,才会对最后答案有贡献。

最后枚举第一步操作的可能性使得xor为0即转入必败态。此时相当于去掉第i个堆里的一个石头,在第j堆和第k堆加上个一块石头。

#include <bits/stdc++.h>using namespace std;const int N=100005;int vis[80],sg[30],num[30];int init(){    sg[1]=0;    for(int i=2;i<=23;i++)    {        memset(vis,0,sizeof(vis));        for(int j=1;j<i;j++)        {            for(int k=1;k<=j;k++)            {                vis[sg[j]^sg[k]]=1;            }        }        for(int q=0;q<80;q++)        {            if(!vis[q])            {                sg[i]=q;                break;            }        }    }    return 0;}int main(){    int n,t=0;    init();    while(scanf("%d",&n)!=EOF)    {        int ans=0;        if(!n) break;        for(int i=1;i<=n;i++)        {            scanf("%d",&num[i]);            if(num[i]&1)            {                ans^=sg[n+1-i];            }        }        cout<<ans<<endl;        printf("Game %d: ",++t);        if(!ans)        {            printf("-1 -1 -1\n");            continue;        }        int flag=1;        for(int i=1;i<=n&&flag;i++)        {            if(num[i])            for(int j=i+1;j<=n&&flag;j++)            {                for(int k=j;k<=n&&flag;k++)                {                    if((ans^sg[n+1-i]^sg[n+1-j]^sg[n+1-k])==0)                    {                        printf("%d %d %d\n",i-1,j-1,k-1);                        flag=0;                    }                }            }        }    }    return 0;}


0 0