博弈論(階梯博弈)POJ 1704

對階梯博弈的闡述:博弈在一列階梯上進行,每個階梯上放着自然數個點。兩個人進行階梯博弈,每一步則是將一個集體上的若干個點( >=1 )移到前面去,最後沒有點可以移動的人輸

證明方式:如這就是一個階梯博弈的初始狀態 2 1 3 2 4 … 只能把後面的點往前面放…如何來分析這個問題呢…其實階梯博弈經過轉換可以變爲Nim..把所有奇數階梯看成N堆石子..做nim..把石子從奇數堆移動到偶數堆可以理解爲拿走石子..就相當於幾個奇數堆的石子在做Nim..( 如所給樣例..2^3^4=5 不爲零所以先手必敗)爲什麼可以這樣來轉化?
假設我們是先手…所給的階梯石子狀態的奇數堆做Nim先手能必勝…我就按照能贏的步驟將奇數堆的石子移動到偶數堆…如果對手也是移動奇數堆..我們繼續移動奇數堆..如果對手將偶數堆的石子移動到了奇數堆..那麼我們緊接着將對手所移動的這麼多石子從那個奇數堆移動到下面的偶數堆…兩次操作後…相當於偶數堆的石子向下移動了幾個..而奇數堆依然是原來的樣子…即爲必勝的狀態…就算後手一直在移動偶數堆的石子到奇數堆..我們就一直跟着他將石子繼續往下移..保持奇數堆不變…如此做下去..我可以跟着後手把偶數堆的石子移動到0..然後你就不能移動這些石子了…所以整個過程..將偶數堆移動到奇數堆不會影響奇數堆做Nim博弈的過程..整個過程可以抽象爲奇數堆的Nim博弈…
其他的情況…先手必輸的…類似推理…只要判斷奇數堆做Nim博弈的情況即可…
爲什麼是隻對奇數堆做Nim就可以…而不是偶數堆呢?…因爲如果是對偶數堆做Nim…對手移動奇數堆的石子到偶數堆..我們跟着移動這些石子到下一個奇數堆…那麼最後是對手把這些石子移動到了0..我們不能繼續跟着移動…就只能去破壞原有的Nim而導致勝負關係的不確定…所以只要對奇數堆做Nim判斷即可知道勝負情況…

即:是否爲必勝態只需要根據當前從第一個臺階開始的編號爲奇數的臺階上石子的數量取異或即可。若異或值爲0則先手必敗
模型變種 POJ 1704

#include<iostream>
#include<algorithm>
using namespace std;
int t;
int n;
int stairs[1010];
int ans ;
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(int i =1;i<= n;i++)
            cin>>stairs[i];
        ans = 0;
        sort(stairs+1,stairs+n+1);  
        int tmp = 0,head =1;
        if(n%2)tmp  = stairs[1] -1,head ++;
        for(int i = head ;i<=n;i+=2)
        {
            tmp ^= (stairs[i+1] - stairs[i]-1);
        }
    //  cout<<ans;
        if(tmp)
            puts("Georgia will win");
        else 
            puts("Bob will win");

    }
    //system("pause");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章