POJ-1704(Georgia and Bob)——博弈论、SG函数

题意:卧槽,我最讨厌英语了,你们自己去其他博客看中文翻译吧。

 

思路:一开始也是想当然,以为石头(请允许我这么叫)的位置xor一下就是SG值,但是在移动的过程中,必然有些石头堆会减少而有些石头堆会增加,这就与NIM相悖,那么这么的出来的结果也是错的。然后我又考虑两两之间的空位xor一下为SG值,但是还是会出现石头堆增加的情况,那么还是错了。然后我偷偷看了一下题解,发现题解主要抓住一点可选择性的相对位置不变,也就是说如果对方将某个石头移动x格,那么我将另一个石头也移动x格的话,那么这两个石头的相对位置(这两个石头之间的空位)是不变的,那么这两步除了将所有石头整体减少外,不会改变SG函数的情况。那么从右到左将石头两两绑定(石头数是偶数那么当然很容易绑定,如果是奇数,那么就把第一个与位置0的虚拟石头绑定),每对石头堆之间的空位数为局面,将这些数xor即可算出SG函数值。那么如果对手移动每一对石头的前一个,那么我就移动相对应的后一个,使得这对石头对的相对位置不变;如果对手移动后一个,那么我就按照NIM游戏的方式移动其它的石头对的后一个,使得SG值为0,那么这个策略一定是最优的。

 

代码:

#include <iostream>
#include <cstdio>
#include <queue>
#include <stack>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 1000+5
#define clr(x,y) memset(x,y,sizeof(x))
typedef long long ll;
int a[maxn];
int main()
{
    int T,n;
    cin>>T;
    while(T--)
    {
        cin>>n;
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        sort(a,a+n);
        int ans=0;
        if(n%2)
        {
            ans=a[0]-0-1;
            for(int i=1;i<n;i+=2)
                ans^=a[i+1]-a[i]-1;
        }
        else
        {
            for(int i=0;i<n;i+=2)
                ans^=a[i+1]-a[i]-1;
        }
        if(!ans)cout<<"Bob will win"<<endl;
        else cout<<"Georgia will win"<<endl;
    }
    return 0;
}


你可能感兴趣的:(博弈论,Nim)