【博弈】 各種博弈的搬運整理

這兩天認識了幾個組合遊戲的基礎模型,希望自己能更新下去。。

Ferguson遊戲

Description

  • Initial

有兩個盒子,一個裝有 m 顆糖,一個裝有 n 顆糖,表示爲 (m, n) .

  • Step

每次清空一個盒子,將另一個盒子裏的糖轉移一些過來,並保證兩個盒子至少各有一顆糖。

  • Win

最後進行轉移糖者勝,無法轉移糖者敗。

Solve

m, n 都爲奇數,先手敗;m, n 至少一個爲偶數,先手勝。

Proof

顯然,初始狀態爲(1, 1),先手必敗;

  • 設 max(m, n) = 2,即初始狀態爲 (1, 2),(2, 1) 或 (2, 2),對於 (1, 2),(2, 1) 先手可以把 1 清空,然後將 2 分爲 (1, 1) ,先手勝;對於 (2, 2) ,先手可以把其中一個 2 清空,然後將另一個 2 分爲 (1, 1) ,先手勝。符合結論。

  • 設 max(m, n) < k 均符合結論,當 max(m, n) = k :

    • 設 m 與 n 至少一個爲偶數(假設m是偶數),則將 n 清空,把 m 分爲兩個奇數 (a, b) ,由於max(a, b) < k ,因此(a, b) 必敗,(m, n) 必勝(利用規則2);

    • 設 m 與 n 均爲奇數,則只能把其中一個數分爲一個奇數 a ,一個偶數 b ,由於max(a, b) < k ,因此對於任何的方式分解出的(a, b) 均必勝,(m, n) 必敗(利用規則1);

    • 故 max(m, n) = k 符合結論。

  • 故對於任意 (m, n) 結論成立。

chomp!遊戲

Description

  • Initial

有一個 m * n 的棋盤,棋盤的每一個格子用(x, y)表示,最左下角是(1, 1),最右上角是(m, n) ;

  • Step

每次可以拿走一個方格,並拿走該方格右邊與上邊的所有方格。

  • Win

誰拿到(1, 1)誰敗。

Solve

當 m = n = 1,先手敗;除此之外,先手均有必勝策略(先手勝)。

Proof

反證法:

假設後手能取得勝利,那麼先手可以第一步拿走(m, n),若後續回合內後手通過拿走(x, y)達到了必勝狀態,先手均可以第一步就拿走(x, y)來達到必勝狀態。
故不存在後手必勝狀態。

由於無法給出構造性證明,所以只能證明先手必勝,而不能給出廣義的必勝策略。

約數遊戲

Description

  • Initial

桌上有 n 個數字:1~n。

  • Step

兩人輪流在選擇一個桌上的數 x ,然後將 x 與 x 的約數都拿走。

  • Win

拿去最後一個數的人勝出(無法選擇數字的人失敗)。

Solve

先手有必勝策略。(先手勝)

Proof

這個遊戲是 chomp! 的思想的應用。

假設後手能取得勝利,那麼先手可以第一步拿走 1,若後續回合內後手通過拿走 x 達到了必勝狀態,先手均可以第一步就拿走 x 來達到必勝狀態。

Bash Game(巴什博弈)

Description

  • Initial

n 個物品堆成一堆。

  • Step

兩個人輪流從這堆物品中取物,規定每次至少取一個,最多取 m 個。

  • Win

最後取光者得勝。(無法取者敗)

Solve

如果 n % (m+1)0,則先手必勝。

Proof

  • 如果 n=m+1 , 顯然,先手無論取多少,後手均可以將剩餘物品一次全取走,所以先手敗。

  • 如果 n=k(m+1),我們從後手的角度來考慮,設先手第一次取走 x 個物品,那麼後手只要再取走 m+1x 個,此時剩餘物品數量變爲 (k1)(m+1) 個,一直重複這個步驟,就可以回到先手面臨 n=m+1 的局面,所以還是先手敗。相當於進行了k次 n=m+1 的遊戲。

  • 如果 n=k(m+1)+s,先手一開始取走 s 個物品,那麼後手就會面臨 n=k(m+1) 的局面,所以先手勝。

  • 結論得證。

例題

  1. 有一個遊戲,在一個n*m的矩陣中起始位置是(1, m),走到終止位置(n, 1);遊戲規則是隻能向左,下,左下方向移動一步,先走到終點的爲獲勝者。(HDU 2147,總共有 n + m 的距離要移動,一次最多移動 2 的距離,故判斷 (n + m)%2 是否爲 0 即可)。

  2. bash博弈變形1——減法博弈:
    兩個人輪流報數,每次至少報一個,最多報十個,誰能報到100者勝。(先手必勝,第一次報1,類似:HDU 2149)
    有一個由n個石子組成的石子堆,兩名玩家輪流從中拿走石子,每次拿走石子的個數只能是集合S中的數。拿走最後一枚石子的玩家獲勝。(狀態轉移即可)

  3. bash博弈變形2:初始狀態下有石子n個,除最後一次外其他每次取物品個數必須在[p,q]之間,最後一次取硬幣的人輸。(HDU 2897)
    這題狀態稍微複雜一些,並且勝負條件與之前相反,一般bash博弈裏每次取個數可以看作在[1,m]之間,勝負手判斷爲 n % (1+m),因此我們可以猜想每次取[p,q]的勝負手判斷爲 n % (p+q),通過驗證猜想我們可以發現如下策略:

    • n=k(p+q) 時,先手第一次取 q 個,隨後的回合若後手取 x 個,先手再取 p+qx 個,那麼最後就會留給後手 p 個,先手勝。
    • n=k(p+q)+s 時,則要分情況考慮:
      1. 若 s 在[1,p]之間,先手取 x,後手可以取 p+qx ,最後留給先手 s 個,後手勝;
      2. 若 s 在(p,p+q)之間,先手任取 x 個 (1sx<p),後手取 y 個,先手可以再取 p+qy ,最後留給後手 s - x 個,先手勝;
//HDU 2897
#include<bits/stdc++.h>
using namespace std;

int main()
{
    int n , p , q ;
    while ( cin >> n >> p >> q ) {
        if ( n % ( p + q ) <= p && n % ( p + q ) ) 
            puts( "LOST" ) ;
        else
            puts( "WIN" ) ;

    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Wythoff’s Game(威佐夫博弈)

Description

  • Initial

有兩堆石子,一堆有 m 個,另一堆有 n 個。

  • Step

雙方輪流取走一些石子,合法的取法有如下兩種:
1. 在一堆石子中取走任意多顆;
2. 在兩堆石子中取走相同多的任意顆.

  • Win

取走最後一顆石子的人爲贏家。

Solve

(1,2)(1,2)(1,2)(2,1)(2,1)(2,1) 視爲同一狀態,
第 k 個必敗狀態是 (\lfloor\frac{\sqrt 5 +1}{2}*k \rfloor+k,\lfloor\frac{\sqrt 5 + 1}{2}*k \rfloor)(5+12k+k,5+12k)(5+12k+k,5+12k)

  • 拓展性質:

    • (m(k),n(k))=(\lfloor\frac{\sqrt 5 + 1}{2}*k \rfloor+k,\lfloor\frac{\sqrt 5 + 1}{2}*k \rfloor)(m(k),n(k))=(5+12k+k,5+12k)(m(k),n(k))=(5+12k+k,5+12k),則 m(k) 也表示前 k 個必敗狀態中沒出現的自然數。

    • 每個自然數都會出現在必敗狀態中且僅會出現一次。

//HDU 1527 模板題
#include<bits/stdc++.h>
using namespace std;

int main()
{
    int a , b ;
    while ( cin >> a >> b ) {
        if ( a < b ) swap( a, b ) ;
        int k = a - b ;
        int n = (int)( k * ( sqrt(5.0) + 1.0 ) / 2 ) ;
        bool win = ( n != b ) ;
        cout << win << endl ;
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Proof

還是打表吧。。

const int N = 50 ;
bool win[100][100] ;
void init() 
{
    memset( win , false , sizeof win ) ;
    for ( int i = 1 ; i <= n ; i++ ) win[i][i] = true ;
    for ( int i = 1 ; i <= n ; i++ ) {
        for ( int j = i+1 ; j <= n ; j++ ) {
            if ( !win[i][j] ) {
                for ( int k = j + 1 ; k <= n ; k++ )
                    win[i][k] = win[k][i] = true ;
                for ( int k = i + 1 ; k <= n ; k++ )
                    win[k][j] = win[j][k] = true ;
                for ( int k = 1 ; k <= n ; k++ )
                    win[i+k][j+k] = win[j+k][i+k] = true ;
            }
        }
    }
    for ( int i = 1 ; i <= n ; i++ )
        for ( int j = i ; j <= n ; j++ ) {
            if ( !win[i][j] ) cout << i << ' ' << j << endl ;
        }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

Fibonacci’s Game (斐波那契博弈)

Description

  • Initial

有一堆個數爲 n >= 2 的石子。

  • Step

雙方輪流取石子,滿足以下條件:
1. 先手不能在第一次把所有的石子取完;
2. 之後每次可以取的石子數介於 1 到對手剛取的石子數的 2 倍之間(包含 1 和對手剛取的石子數的 2 倍)。

  • Win

取走最後一個石子的人爲贏家。

Solve

如果 n 是斐波那契數,則後手勝;反之,先手勝。

\\HDU 2516 模板題
#include<bits/stdc++.h>
using namespace std;

const string win[2] = { "Second win" , "First win" } ;
long long fib[100] ;
int init() 
{
    fib[0] = 1 ; fib[1] = 1 ;
    for ( int i = 2 ; i < 100 ; i++ ) {
        fib[i] = fib[i-1] + fib[i-2] ;
        if ( fib[i] > ( 1LL << 35 ) ) return i ;
    }
    return 100 ;
}
int main()
{
    int n ; int len = init() ;
    while ( cin >> n && n ) {
        int ok = 1 ;
        for ( int i = 0 ; i <= len ; i++ ) {
            if ( fib[i] == n ) {
                ok = 0 ;
                break ;
            }
        }
        cout << win[ok] << endl ;
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

Proof

Zeckendorf定理:任何正整數可以表示爲若干個不連續的 Fibonacci 數之和。

先手必須從 <= n / 3 的數量開始取(例如第一次取的數量 > n/3,那麼後手可以直接取完所有剩下石子)
於是。。。太繞了!
還是請看Acdream大神的吧。。http://blog.csdn.net/acdreamers/article/details/8586135

Nim遊戲(待施工)

Description

有三堆各若干個物品,兩個人輪流從某一堆取任意多的
物品,規定每次至少取一個,多者不限,最後取光者得勝。

Solve

介紹這個遊戲的太多了。。偷個懶
具體解法就是異或異或!

以下內容來自轉載:

博弈問題簡介

所討論的博弈問題滿足以下條件:

  1. 玩家只有兩個人,輪流做出決策
  2. 遊戲的狀態集有限,保證遊戲在有限步後結束,這樣必然會產生不能操作者,其輸
  3. 對任何一種局面,勝負只決定於局面本身,而與輪到哪位選手無關

一般稱滿足以上條件的遊戲稱爲ICG,比如我們將要討論的Nim遊戲。作爲一個對比,我們平時玩的象棋就不屬於ICG,因爲它不滿足第三條。

ICG具有兩個狀態,我們稱爲必勝態和必敗態,他們的關係:

後繼狀態能達到必敗的狀態爲必勝態

所有後繼狀態都不爲必敗態,則其爲必敗態

第二條也可以換一種說法:後繼狀態都是必勝態,則其爲必敗態。 所以我們可以看出一個狀態不是必勝態,就是必敗態。


取石子游戲NIM

取石子游戲是一個古老的博弈遊戲,發源於中國,它是組合數學領域的一個經典問題。它有許多不同的玩法,基本上是兩個玩家,玩的形式是輪流抓石子,勝利的標準是抓走了最後的石子。

玩家設定: 先取石子的是玩家A,後取石子的是玩家B。

經典的三種玩法

一、巴什博奕(Bash Game),有1堆含n個石子,兩個人輪流從這堆物品中取物,規定每次至少取1個,最多取m個。取走最後石子的人獲勝。

二、尼姆博奕(Nimm Game),有k堆各n個石子,兩個人輪流從某一堆取任意多的物品,規定每次至少取一個,多者不限。取走最後石子的人獲勝。

三、威佐夫博奕(Wythoff Game),有2堆各n個石子,兩個人輪流從某一堆或同時從兩堆中取同樣多的物品,規定每次至少取1個,多者不限。取走最後石子的人獲勝。POJ1067

平衡狀態的概念:

   引入一個概念,平衡狀態,又稱作奇異局勢。當面對這個局勢時則會失敗。任意非平衡態經過一次操作可以變爲平衡態。每個玩家都會努力使自己抓完石子之後的局勢爲平衡,將這個平衡局勢留給對方。因此,玩家A能夠在初始爲非平衡的遊戲中取勝,玩家B能夠在初始爲平衡的遊戲中取勝。

http://blog.csdn.net/pipisorry/article/details/39249337


取石子游戲不同玩法的解決方案

玩法一(1堆n個石子每次最多取m個)

顯然,如果n=m+1,那麼由於一次最多隻能取m個,所以,無論先取者拿走多少個,後取者都能夠一次拿走剩餘的物品,後者取勝。因此我們發現瞭如何取勝的法則:如果n=(m+1)r+s,(r爲任意自然數,s≤m),那麼先取者要拿走s個物品,如果後取者拿走k(≤m)個,那麼先取者再拿走m+1-k個,結果剩下(m+1)(r-1)個,以後保持這樣的取法,那麼先取者肯定獲勝。總之,要保持給對手留下(m+1)的倍數,就能最後獲勝。

即,若n=k*(m+1),則後取着勝,反之,存在先取者獲勝的取法。n%(m+1)==0. 先取者必敗

奇異局勢的判定

    一般的奇異局勢是n=(m+1)*i,其中i爲自然數,即n%(m+1)=0,面對這種情況無論我怎麼取,對方總可以將其恢復爲n%(m+1)=0,一直到n=(m+1)局勢。

玩家的策略

    就是把當前面對的非奇異局勢變爲奇異局勢留給對方。如果當前的石子個數爲(m+1)*i+s,那麼就將s個石子取走,使其達到奇異局勢。

變相的玩法

兩個人輪流報數,每次至少報一個,最多報十個,誰能報到100者勝。(<=>從一堆100個石子中取石子,最後取完的勝)

最後一個奇異局勢是n=(0)。一種奇異局勢是,n=(m+1),那麼無論我取走多少個,對方都能夠一次取走剩餘所有的物品取勝。


http://blog.csdn.net/pipisorry/article/details/39249337


玩法二(k堆石子每次只從1堆取)

簡化問題:有三堆各若干個物品,兩個人輪流從某一堆取任意多的物品,規定每次至少取一個,多者不限,最後取光者得勝。

    這種情況最有意思,它與二進制有密切關係,我們用(a,b,c)表示某種局勢,首先(0,0,0)顯然是奇異局勢,無論誰面對奇異局勢,都必然失敗。第二種奇異局勢是(0,n,n),只要與對手拿走一樣多的物品,最後都將導致(0,0,0)。仔細分析一下,(1,2,3)也是奇異局勢,無論對手如何拿,接下來都可以變爲(0,n,n)的情形。
    計算機算法裏面有一種叫做按位模2加,也叫做異或的運算,我們用符號(+)表示這種運算。這種運算和一般加法不同的一點是1+1=0。先看(1,2,3)的按位模2加的結果:
1 =二進制01
2 =二進制10
3 =二進制11 (+)
———————
0 =二進制00 (注意不進位)
    對於奇異局勢(0,n,n)也一樣,結果也是0。
    任何奇異局勢(a,b,c)都有a(+)b(+)c =0。
如果我們面對的是一個非奇異局勢(a,b,c),要如何變爲奇異局勢呢?假設 a < b< c,我們只要將 c 變爲 a(+)b,即可,因爲有如下的運算結果: a(+)b(+)(a(+)b)=(a(+)a)(+)(b(+)b)=0(+)0=0。要將c 變爲a(+)b,只要從 c中減去 c-(a(+)b)即可。

獲勝情況對先取者的討論

異或結果爲0,先取者必敗,無獲勝方法。後取者獲勝;

結果不爲0,先取者有獲勝的取法。

奇異局勢的判定

    對於一個普通的局勢,如何判斷其是不是奇異局勢?對於一個局勢(s1,s2,...sk),對所有石子個數做位的異或運算,s1^s2^s3^...^sk,如果結果爲0,那麼局勢(s1,s2,...sk)就是奇異局勢(平衡),否則就不是(非平衡)。從二進制位的角度上說,奇異局勢時,每一個bit位上1的個數都是偶數。

玩家的策略

    就是把面對的非奇異局勢變爲奇異局勢留給對方。也就是從某一堆取出若干石子之後,使得每一個bit位上1的個數都變爲偶數,這樣的取法一般不只有一種。可以將其中一堆的石子數變爲其他堆石子數的位異或運算的值(如果這個值比原來的石子數小的話)。

拓展

任給N堆石子,兩人輪流從任一堆中任取(每次只能取自一堆),取最後一顆石子的人獲勝,問先取的人如何獲勝?

根據上面所述,N個數異或即可。如果開始的時候T=0,那麼先取者必敗,如果開始的時候T>0,那麼只要每次取出石子使得T=0,即先取者有獲勝的方法。

最後一個奇異局勢是(0,0...,0)。另一個奇異局勢是(n,n,0...0),只要對手總是和我拿走一樣多的物品,最後會面對(0,0...,0)。

http://blog.csdn.net/pipisorry/article/details/39249337


玩法三(2堆石子每次從一或兩堆取一樣數目的石子)

    前幾個奇異局勢是:(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。。。

奇異局勢的判定

可以看出,a0=b0=0,ak是未在前面出現過的最小自然數,而 bk= ak + k,奇異局勢有如下三條性質:
    1、任何自然數都包含在一個且僅有一個奇異局勢中。
    由於ak是未在前面出現過的最小自然數,所以有ak > ak-1 ,而 bk= ak + k > ak-1 + k-1 = bk-1 > ak-1 。所以性質1。成立。
    2、任意操作都可將奇異局勢變爲非奇異局勢。
    事實上,若只改變奇異局勢(ak,bk)的某一個分量,那麼另一個分量不可能在其他奇異局勢中,所以必然是非奇異局勢。如果使(ak,bk)的兩個分量同時減少,則由於其差不變,且不可能是其他奇異局勢的差,因此也是非奇異局勢。
    3、採用適當的方法,可以將非奇異局勢變爲奇異局勢。假設面對的局勢是(a,b),若 b = a,則同時從兩堆中取走 a 個物體,就變爲了奇異局勢(0,0);如果a = ak ,b > bk,那麼,取走b - bk個物體,即變爲奇異局勢;如果 a = ak , b < bk ,則同時從兩堆中拿走 ak - ab - ak個物體,變爲奇異局勢( ab - ak , ab - ak+ b - ak);如果a > ak ,b= ak + k,則從第一堆中拿走多餘的數量a - ak 即可;如果a < ak ,b= ak + k,分兩種情況,第一種,a=aj (j < k),從第二堆裏面拿走 b - bj 即可;第二種,a=bj (j < k),從第二堆裏面拿走 b - aj 即可。
    從如上性質可知,兩個人如果都採用正確操作,那麼面對非奇異局勢,先拿者必勝;反之,則後拿者取勝。
那麼任給一個局勢(a,b),怎樣判斷它是不是奇異局勢呢?
這個奇異局勢的序列的通項公式可以表示爲:(推導見附錄)

  Ak = [k*(1+sqrt(5.0)/2]

  Bk = Ak + k  

  其中k=0,1,2,...,n ,方括號表示int取整函數。

有了這個通項式子,逆向的,對於某一個局勢,只需要判斷其A是否是黃金分割數的某個k的倍數,然後再確認B是否等於A+k即可。


奇妙的是其中出現了黃金分割數(1+√5)/2 = 1.618...,因此,由ak,bk組成的矩形近似爲黃金矩形,由於2/(1+√5)=(√5-1)/2,可以先求出j=[a(√5-1)/2],若a=[j(1+√5)/2],那麼a = aj,bj = aj + j,若不等於,那麼a = aj+1,bj+1 = aj+1+ j + 1,若都不是,那麼就不是奇異局勢。然後再按照上述法則進行,一定會遇到奇異局勢。    

我們會發現這個序列的規律,設序列第k個奇異局勢元素爲(Ak,Bk),k爲自然數。那麼,初始條件k=0時是,A0=B0=0,遞推關係爲下一個奇異局勢的Ak是未在前面出現過的最小自然數,且Ak = Bk + k。

變種玩法

“皇后登山”遊戲,在空的圍棋棋盤上放一個棋子,該棋子每次只能向上或向右或沿對角線向右上方向移動(相似國際象棋),可以移動任意格,但不能不移動,兩人輪流移動棋子,先將棋子移動到右上角者贏,問先移棋者的必勝策略。《智力遊戲中的數學方法》。code:

[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. /****************************************************************************/  
  2. /*      編程之美 - NIM撿石子問題 皮皮 2014-9-10        */  
  3. /****************************************************************************/  
  4. #include <assert.h>  
  5. #include <stdio.h>  
  6. #include <math.h>  
  7.   
  8. /*  黃金分割數最優算法   */  
  9. static int nim(int x, int y){  
  10.     double a = (sqrt(5.0) + 1) / 2;             //goldenNum 1.618...  
  11.     int n = abs(x - y);                         //bn - an  
  12.     x = x < y? x : y;                            //取小者  
  13.     return ( x != int(a * n) );  
  14. }  
  15.   
  16. int main(){  
  17.     int x, y;  
  18.     while(scanf("%d%d", &x, &y) == 2)  
  19.         printf("%d\n", nim(x, y));  
  20.     return 0;  
  21. }  
http://blog.csdn.net/pipisorry/article/details/39249337



尼姆博奕的分解解釋

  • 例一

有一堆石子,兩個人輪流從石子堆中拿走任意數量的石子,但不能不拿。誰不能拿誰爲輸。

顯然,這個遊戲中只要先手把所有石子都拿完,那麼後手就一定輸了。因爲此時沒有石子,後手無法進行合法的操作。

  • 例二

有兩堆石子,分別爲a,b個石子,每個玩家只能選一堆,然後拿走任意正整數個石子,誰不能拿誰輸。

我們先討論一個特殊情況,即:a=b時,此時後手是必勝的。此時不管先手怎麼操作,我們只要選擇與先手不同的那堆,然後進行與先手相同的操作即可。

這裏a=b即爲我們所說的必敗態。而當a≠b時,我們肯定可以拿比較多的那堆,使之和少的那堆數量相等,此時我們就必勝了,所以此時就爲必勝態。

  • 例三(二、尼姆博奕的另一種解釋

當有三堆,數量分別爲a,b,c時,我們就比較不好分析了。當然我們可以直接搜索得到最後結果,但是當我們拓展到n堆時(相當於二、尼姆博奕),此時我們搜索也變得不可行了。

於是我們有了一個強大的工具:sg函數

sg函數

sg函數爲以下形式:SG(x)=mex(S)

S表示x的所有後繼狀態

mex表示不在集合裏最小的非負整數

  • 必敗態的sg值爲0
  • 然後還要結合sg定理SGSGNim
  • 於是就可以把各個子游戲分而治之。
  • 舉個例子

假設我們用sg函數處理上述所說的例二,我們就可以把遊戲分爲兩個單堆Nim子游戲。對於單堆的Nim遊戲,如果我們可以取任意正整數多個,那麼很容易就可以明,sg(x)=x。那麼我們整個遊戲的必敗態則爲sg1(x)sg2(x)=0顯然只有當a=b時遊戲爲必敗態,和我們的討論結果一致。

關於sg定理的證明

對於必勝狀態,一定存在後繼的必敗態

我們假設現在的Nim和爲X,現在的最大的一堆的數量爲Y,那麼我們只需要把這最大的一堆取成Z=X∧Y即可。因爲除了最大的這堆外其他的Nim和爲X∧Y,因此我們取完後,現在的Nim和即爲sg′(X)=X∧Y∧(X∧Y)=0,顯然爲必敗態了。而且我們也可以保證Z≤Y,即我們總有辦法實現它。

  • 對於必敗態,它的所有後繼狀態都是必勝的

由於只能更改一堆的狀態,無論哪一位的1被改變,那麼原來那位上1的奇偶個數一定會改變,所以就會變爲必勝態。

[博弈問題入門]


拓展:?

 綜合一、三

任給N堆石子,兩人輪流從任一堆中任取(每次只能取自一堆),規定每方每次最多取K顆,取最後一顆石子的一方獲勝.問先取的人如何獲勝?

與上面的問題比,這個更復雜一些,我們可以這樣做

令Bi=Ai mod(K+1)

定義T‘=B1 xor B2 xor ... xor Bn

如果T‘=0 那麼沒有獲勝可能,先取者必敗

如果T’>0 那麼必然存在取的方法,使得T‘=0,先取者有獲勝的方法

假設對方取了在Ai中取了r<=K個

如果Ai中剩下的石子多於K 那麼就在Ai中取走K+1-r個則Bi不變 T‘還是0

如果Ai<=K 那麼我們需要重新計算Bi和T‘ 按照上面的方法來做就可以了

固定多個數目取石子

Alice和Bob在玩一個取石子游戲,規則如下:
1,Alice先手,兩人輪流取,每次可以取1/2/4顆。
2,取走最後一顆石子的人勝出。
問題:
1,共有16顆石子時,誰將勝出?
2,共有n (n>=1) 顆石子時,誰將勝出?

分析:

Alice的必勝態:
當Alice取完本輪石子後,剩下的石子爲3的倍數(3*n),那麼無論Bob怎麼取,Alice都會贏。
簡單解釋如下:
①n = 1時,即Alice取完後只剩下3顆,那麼無論Bob怎麼取,Alice下次取都會取到最後一顆,會贏。
②n >1時,即Alice取完後剩下3*n顆,當Bob取完後,剩下的石子數量總可以表示爲:
3*k+1 或 3*k + 2(k >= 0),那麼此時Alice可以將剩下的石子數重新變爲3的倍數,如此遞推下去。
...
最終剩下石子數量變爲3。也就是說,只要Alice取完後,剩下的石子數是3的倍數,那麼Alice肯定會贏。

即n%3==0時Alice輸,否則贏(都按最優策略取石子)

簡化約數博弈

兩個人輪流在黑板上寫一個不大於10的正整數。規定不準把已經寫過的數的約數再寫出來。誰最後沒寫的了誰就輸了。問是先寫的人必勝還是後寫的人必勝,必勝策略是什麼。
分析:先寫者有必勝策略。他可以先寫下數字6,現在就只剩下4、5、7、8、9、10可以寫了。把剩下的6個數分成三對,分別是(4,5)、(7,9)、(8,10),每一對裏的兩個數都不成倍數關係,且它們各自的倍數(如果出現過)必然是同時出現。因此不管你寫什麼數,我就寫它所在的數對裏的另一個數,這樣可以保證我總有寫的。

[小學奧賽的經典題目]

約數博弈

甲乙兩個人玩一個博弈遊戲。遊戲初始狀態包含1-n, 這n個正整數。
甲乙兩個人輪流玩這個遊戲。每輪遊戲中,遊戲者任意選擇一個還存在的數,然後刪掉它和它所有的約數。
誰最後沒有數可刪,誰就輸掉了。
問題:他們都足夠聰明,甲先開始,請分析誰有必勝策略?

分析:先手有必勝策略。這個證明不是構造性的,也就是說沒有給出先手怎麼下才能贏。反證法:假設後手B有必勝策略,而先手A第一次取數1,B取了一個數x是必勝策略,然而A完全可以第一次取x(同時也必取了1)是必勝策略。故B必沒有必勝策略。

不過lz有一種比較暴力的策略不知對否:將所有數據分成數對(除數1外每個數對都不是約數),對手取完一個數後,如果剩下的是奇數,則取一個合適的數讓剩下的數可以重新分對,如果剩下的是偶數,則取一個合適的數(這個數的約數有奇數個),剩下的數仍可以重新分對。這樣對手不管取哪個數,總有一個與對手取的數不是約數的數可以給你取。

Note:整數a除以整數b(b≠0) 除得的商正好是整數而沒有餘數,我們就說a能被b整除,或b能整除a。a稱爲b的倍數,b稱爲a的約數。一個數的約數必然包括1及其本身。任何正整數都是0的約數。

變型:考慮一個新的規則“不準寫數字1”。如果加上這個新規則後先寫者有必勝策略,那麼這個策略對於原遊戲同樣適用(因爲1是所有數的約數,本來就不能寫);如果在新規則下後寫者必勝,則原遊戲中的先寫者寫下數字1,然後他就變成了新規則下的後寫者。於是不管怎麼樣,先寫者總是有必勝策略。

只要是雙方共用狀態(合法的決策完全相同)的對弈遊戲,其中一方肯定有必勝策略。棋局的任一狀態只有兩種,面對這個棋局的人要麼必勝要麼必敗。考慮這樣的一個遞推關係:如果一個狀態是必勝態,那至少有一種走法能走成一個必敗態留給對方;如果一個狀態是必敗態,那它怎麼走都只能走到必勝態。運用這樣的關係,我們可以自底向上推出初始狀態是必勝還是必敗。     
    這種分析方法有一種很形象的名字叫做Strategy-stealing,它的另一個經典例子是Chomp遊戲。上面所舉的例子都是雙方共用狀態的遊戲(ICG遊戲),因此至少有一方存在必勝策略。對於其它一些非ICG遊戲,我們也可以用類似的方法證明後手不可能有必勝策略(但在這裏並不能說明先手一定必勝)。比如對於井字棋遊戲,假設後手有必勝策略,那先手就隨便走一步,以後就裝成是後手來應對。如果在哪一步需要先手在已經下過子的地方落子,他就再隨便走一步就是了。這種證明方法成立的前提就是,多走一步肯定不是壞事。事實上,對於所有這種“多走一步肯定不是壞事”的且決策對稱的遊戲,我們都可以證明後手是沒有必勝策略的。

[博弈問題入門]

Chomp!博弈(巧克力遊戲)

有一個n*m的棋盤,每次可以取走一個方格並拿掉它右邊和上面的所有方格。拿到左下角的格子(1,1)者輸,如下圖是8*3的

棋盤中拿掉(6,2)和(2,3)後的狀態。




結論:答案是除了1*1的棋盤,對於其他大小的棋盤,先手總能贏。

分析:有一個很巧妙的證明可以保證先手存在必勝策略,可惜這個證明不是構造性的,也就是說沒有給出先手怎麼下才能贏。

證明如下:如果後手能贏,也就是說後手有必勝策略,使得無論先手第一次取哪個石子,後手都能獲得最後的勝利。那麼現在假設先手

取最右上角的石子(n,m),接下來後手通過某種取法使得自己進入必勝的局面。但事實上,先手在第一次取的時候就可以和

後手這次取的一樣,進入必勝局面了,與假設矛盾。

約數和倍數博弈

給定的一些自然數,如 2,3,4,5,6,。。。,兩人依次拿數,連同該數的約數和倍數一起拿掉,如拿2要連4,6一起拿掉;拿6要連帶2,3一起拿掉。最後總有一人沒法拿了(因爲數都拿光了),就算輸。

舉例:
2,3,4
先拿者不管怎樣拿都是輸。先出2題:
題1:初始數據 2,3,4,5,6,7,8,9,10             共9個數字。
題2:初始數據 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18        共17個數字。
問:先拿者贏還是輸,如果贏的話,第一步怎樣拿?

[智能博弈題]

其它類似題型

POJ1740A New Stone Game
MIPT 100 Nim Game -- who is the winner? 
POJ 1704 Georgia and Bob

樓梯Nim:就是把樓梯上的棋子兩兩綁定,他們之間的距離看成是一堆石子,於是就等同於我們之前討論的經典Nim遊戲了。

Moore’s Nimk:廣義的Nim遊戲。有n堆石子,每次最少選一堆,最多選m堆,每堆都可以拿任意正整數個石子。我們把每堆石子都寫成二進制的形式,然後從低位到高位求每一位1的和。如果每一位1的和sum%(m+1)=0此時爲必敗態。顯然,當m=1時就變成了我們最開始所討論的最基礎的Nim遊戲了。

翻硬幣遊戲:這類題目比較複雜,一般打表找規律。

圖的刪邊遊戲

[藍橋杯 歷屆試題 約數倍數選卡片]

http://blog.csdn.net/pipisorry/article/details/39249337



附錄

1.Wythoff’s Game (威佐夫博弈)的解釋[類似解釋亦可見於編程之美NIM(3)]

Wythoff's Nim

有兩堆石子,不妨先認爲一堆有10,另一堆有15個,雙方輪流取走一些石子,合法的取法有如下兩種:

1)在一堆石子中取走任意多顆;

2)在兩堆石子中取走相同多的任意顆;

約定取走最後一顆石子的人爲贏家,求必敗態(必勝策略)。

這個可以說是MR.Wythoff(於1907年提出此遊戲)一生全部的貢獻。不知道高斯取整函數與Beatty定理,所做的只能是找規律而已。可以先在http://www.cut-the-knot.org/pythagoras/withoff.shtml玩幾局。

簡單分析一下,容易知道兩堆石頭地位是一樣的,我們用餘下的石子數(a,b)來表示狀態,並畫在平面直角座標系上。

用定理: 有限個結點的無迴路有向圖有唯一的核  中所述的方法尋找必敗態。先標出(0,0),然後劃去所有(0,k),(k,0),(k,k)的格點;然後找y=x上方未被劃去的格點,標出(1,2),然後劃去(1,k),(k,2),(1+k,2+k),同時標出對稱點(2,1),劃去(2,k),(1,k),(2+k,1+k);然後在未被劃去的點中在y=x上方再找出(3,5)。。。按照這樣的方法做下去,如果只列出a<=b的必敗態的話,前面的一些是(0,0),(1,2),(3,5),(4,7),(6,10),…

接下來就是找規律的過程了,忽略(0,0),記第n組必敗態爲(a[n],b[n])

命題一:a[n+1]=前n組必敗態中未出現過的最小正整數

[分析]:如果a[n+1]不是未出現的數中最小的,那麼可以從a[n+1]的狀態走到一個使a[n+1]更小的狀態,和我們的尋找方法矛盾。

命題二:b[n]=a[n]+n

[分析]:歸納法:若前k個必敗態分別爲 ,下證:第k+1個必敗態爲

從該第k+1個必敗態出發,一共可能走向三類狀態,從左邊堆拿走一些,從右邊堆拿走一些,或者從兩堆中拿走一些.下面證明這三類都是勝態.

情況一:由命題一,任意一個比a[k+1]小的數都在之前的必敗態中出現過,一旦把左邊堆拿少了,我們只要再拿成那個數相應的必敗態即可。

情況二(從右邊堆拿走不太多):這使得兩堆之間的差變小了,比如拿成了 ,則可再拿成 ;

情況二(從右邊堆拿走很多):使得右邊一堆比左邊一堆更少,這時類似於情況一,比如拿成了 (其中a[m] ;

情況三:比如拿成 ,則可再拿成 .

綜上所述,任何從 出發走向的狀態都可以走回核中.故原命題成立.

以上兩個命題對於確定(a[n],b[n])是完備的了,給定(0,0)然後按照這兩個命題,就可以寫出(1,2),(3,5),(4,7),…

這樣我們得到了這個數列的遞推式,以下我們把這兩個命題當成是(a[n],b[n])的定義。

先證明兩個性質:

性質一:核中的a[n],b[n]遍歷所有正整數。

[分析]:由命題一,二可得a[n],b[n]是遞增的,且由a[n]的定義顯然。

性質二:A={a[n]:n=1,2,3,…},B={b[n]:n=1,2,3,…},則集合A,B不交。

[分析]:由核是內固集,顯然。


實際上a[n]和b[n]就是一個Beatty序列。

(Betty 定理)

如果存在正無理數 A, B 滿足 1/A + 1/B = 1,那麼集合 P = { [A*t], t ∈ Z+}、Q = { [B*t], t ∈ Z+} 恰爲集合 Z+ 的一個劃分,即:P ∪ Q = Z+,P ∩ Q = ø。證明見附錄2。
考慮到Betty定理中“恰爲Z+的劃分”這一說,這意味着,Z+中的每個數都恰好出現一次,與上述矩陣的性質十分吻合。

於是我們猜想每一行第一列的數滿足 [Φi] 的形式,得到每一行第二列的數爲 [Φi] + i = [Φi + i] = [(Φ + 1)i]

我們的目的是要讓 Z+ 中每個數都在這個矩陣中出現,於是考慮到 Betty 定理的條件,Φ 和 (Φ + 1) 應滿足 1/Φ + 1/(Φ + 1) = 1。解這個方程,我們得到 Φ = (sqrt(5) + 1) / 2,於是 Φ + 1 = (sqrt(5) + 3) / 2。 ,到此,我們找到了該必敗態的通項公式。

實際上這組Beatty序列還有一些別的性質,比如當一個數是Fibonacci數的時候,另一個數也是Fibonacci數;而且兩者的比值也越來越接近黃金比,這些性質在得到通項公式之後不難證明。

啓示:首先用定理所說的方法找核,然後給出核的規律(遞推,或是通項)並且證明。

附上一張對應的必敗態圖

wythoff


2.Betti theorem:
設a、b是正無理數且1/a+1/b=1。記P={[na]|n爲任意的正整數},Q={[nb]|n爲任意的正整數},([x]'指的是取x的整數部分)則P與Q是Z+的一個劃分,即P∩Q爲空集且P∪Q爲正整數集合Z+。
證明:
因爲a、b爲正且1/a+1/b=1,則a、b>1,所以對於不同的整數n,[na]各不相同,類似對b有相同的結果。因此任一個整數至多在集合P或Q中出現一次。
* 現證明P∩Q爲空集(反證法):假設k爲P∩Q的一個整數,則存在正整數m、n使得[ma]=[nb]=k。即k < ma、nb<k+1,等價地改寫不等式爲
 m/(k+1)< 1/a < m/k及n/(k+1)< 1/b < n/k。相加起來得 (m+n)/(k+1) < 1 < (m+n)/k,即 k < m+n < k+1。這與m、n爲整數有矛盾,所以P∩Q爲空集。
 *現證明Z+=P∪Q:已知P∪Q是Z+的子集,剩下來只要證明Z+是P∪Q的子集。(反證法)假設Z+\(P∪Q)有一個元素k,則存在正整數m、n使得[ma]< k <[(m+1)a]、[nb]< k <[(n+1)b]。 由此得ma < k ≦[ (m+1)a]-1<(m+1)a -1(因爲a是無理數),類似地有nb < k ≦[ (n+1)b]-1<(n+1)b -1。等價地改寫爲 m/k < 1/a < (m+1)/(k+1)及n/k < 1/b < (n+1)/(k+1)。兩式加起來,得
(m+n)/k < 1 < (m+n+2)/(k+1),即m+n < k < k+1 < m+n+2。這與m, n, k皆爲正整數矛盾。
所以Z+=P∪Q。[貝蒂定理]

from:http://blog.csdn.net/pipisorry/article/details/39249337

ref:http://www.cnblogs.com/celia01/archive/2011/11/15/2250171.html

http://blog.csdn.NET/ojshilu/article/details/16812173

http://yjq24.blogbus.com/logs/42826226.html

POJ 1067 取石子游戲

1.13 NIM(3)兩堆石頭的遊戲

狀態作爲結點可以畫一張有向圖

編程之美讀書筆記_1.13 NIM(3)兩堆石頭的遊戲

編程之美1.13——NIM(3)兩堆石頭的遊戲

尼姆博奕(Nimm Game)

博弈算法入門小節 1536 1517 1907


轉自: http://blog.csdn.net/qq_33765907/article/details/51174524http://blog.csdn.net/qq_15714857/article/details/49691585
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章