1. 程式人生 > >博弈論——nim

博弈論——nim

大致上是這樣的:有兩堆石子,不妨先認為一堆有10,另一堆有15個,雙方輪流取走一些石子,合法的取法有如下兩種:

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

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

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

這個可以說是MR.Wythoff(Wythoff於1907年提出此遊戲)一生全部的貢獻吧,我在一篇日誌裡就說完有點殘酷。這個問題好像被用作程式設計競賽的題目,網上有很多把它Label為POJ1067,不過如果學程式設計的人不知道Beatty定理和Beatty序列 ,他們所做的只能是找規律而已。不熟悉的人可以先在這裡玩幾局~

簡單分析一下,容易知道兩堆石頭地位是一樣的,我們用餘下的石子數(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不交。

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

看到這裡大家有沒有想到Beatty序列呢,實際上a[n]和b[n]就是一個Beatty序列。

 ,有  ,解方程 

得  ,到此,我們找到了該必敗態的通項公式。

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

總的來說,這個問題給我們了哪些啟示呢?首先用定理所說的方法找核,然後給出核的規律(遞推,或是通項)並且證明。最後附上一張對應的必敗態圖.

 補充:貝亞蒂定理證明威佐夫定理:

 用有序數對(即兩堆含石子的個數,規定第一個數不大於第二個數)表示某個狀態,顯然(0,0)是一個必敗態。下面證明,根據下面的方法,可以構造出所有的必敗態:

    1° (0,0)是必敗態;

    2° 第k個必敗態的兩個數相差為k(記(0,0)為第0個必敗態);

    3° 已知前k個必敗態,則最小的沒出現過的正整數為第k+1個必敗態的第一個數。

    分情況討論,很容易就把這件事說清楚了,下面幾段證明可以跳過

    證明:根據上述構造方法,有一個顯然的事實,就是每個狀態的第一個數比它後面一個狀態的第一個數小,對第二個數也如此【1】。假如說後面狀態的第一個數(記為A)比前面的小,那麼前面狀態的第一個數早就選A了,肯定輪不到後面的狀態,與 3°矛盾。而前面狀態中第二個數減第一個數的值比後面的小(由 2°),所以前面狀態中第二個數當然比後面的小。

    同時,也可知不會出現重複的正整數【2】,因為如果出現重複的正整數,一定是前面狀態的第二個數等於後面狀態的第一個數(否則,由[1],將會出現嚴格不等關係)。而後面狀態的第一個數不可能與前面重複,與 3°矛盾。

    現在,考慮構造出的第n個狀態,當n=0時顯然是必敗態,設n=0,1,2,…,k-1時,這k個狀態已經是必敗態,下面證明第k個狀態也是必敗態。

    記此狀態為(A,A+k)。先取者不可能變為前面的必敗態,因為如果只動一堆石子而變為前面某個必敗態,則兩個必敗態有重複的正整數,矛盾;如果動兩堆石子,則差不變,同樣不可能變為前面某個必敗態。

    下面通過證明,先取者不管如何取石子,後取者都能變成前面某個必敗態,從而證明(A,A+k)也是必敗態。

    (1)先取者若動第一堆石子,則這個數肯定在前面的必敗態中出現過(由 3°),而此時第二堆石子的數目肯定比前面那個必敗態的兩個數都要大(由 [1]),所以後取者一定可以取第二堆石子,變為前面那個必敗態。

    (2)先取者若動第二堆石子:

         i .如果取完之後第二堆仍然不小於第一堆,則兩堆石子的差減小,恰好和前面某個必敗態吻合,而第一堆石子的數目肯定比前面那個必敗態的第一個數大(由 [1]),後取者可以同時取兩堆石子變為前面那個必敗態。

         ii.若小於第一堆,則這個數在前面的必敗態中出現過(由 3°),如果這個數是前面必敗態的第二個數,則後取者只要動第一堆即可;如果很不巧,這個數是前面必敗態的第一個數,而此時第一堆石子的數目又不大於前面必敗態的第二個數,那此時兩堆石子的差一定比前面那個必敗態小,與更靠前的一個必敗態吻合。後取者同時動兩堆即可。

    (3)先取者若同時動兩堆石子,則第一堆石子數在前面的必敗態中出現過(由 3°),後取者動第二堆就行了。

    這就證完了

    由剛才的構造必敗態的方法,記{a_n},{b_n}分別為第一個數與第二個數構成的數列(除去第一對(0,0)),n=1,2,3, … ,先寫出兩個數列的前幾項:

    {a_n}: 1,3,4,6,…

    {b_n}: 2,5,7,10,…

    根據剛才的構造方法,顯然兩個數列都是嚴格遞增的,而且沒有重複的正整數,而且每一個正整數都會出現(由 3°,不可能漏掉某個正整數),且b_n-a_n=n。

    熟悉Beatty定理的人會立即看出,Beatty定理構造的數列恰好滿足前三條!

    下面先介紹一下Beatty定理。

    取正無理數α,β,使得

    構造兩個數列{a_n},{b_n},它們的通項分別為

    a_n為小於等於αn的最大整數,那個符號相當於高斯函式[ ]。

    數列顯然都是正整數數列,Beatty定理指出,兩個數列都是嚴格遞增的,並且每個正整數在兩個數列中出現且僅出現一次。

    嚴格遞增好證,因為 1/α<1,α>1 ,所以{a_n}相鄰兩項取整前相減大於1,取整後後面一項顯然也大於前面一項。對{b_n}同理。

    對於後一個命題,我們只要證明,對於任意正整數k,小於等於k的正整數在兩個數列中恰好出現k次。

    設數列{a_n}的前p項小於等於k(而不含p+1項),又因為每一項取整前均為無理數,不可能取到整數值,於是有

    兩者綜合起來,就有等式

    這就是小於等於k的正整數在數列{a_n}中出現的次數。對於數列{b_n}同理。這樣我們得到了小於等於k的正整數在兩個數列中出現的總次數

    注意到,兩個向下取整符號內的數均為無理數,於是有嚴格的不等式

    於是有

    這就證完了。

    回到剛才的必敗態上,Beatty定理是一個很合適的定理,任取一組滿足要求的α,β,構造出的數列就滿足大部分條件,只剩最後一個條件,即 b_n-a_n=n,這隻需取 β-α=1 即可。

    解出α,β的值如下:

    於是,我們就可以直接寫出第n個必敗態的公式

    至此,開始那個取石子游戲得到完美解決,而黃金分割數,竟然在一個看似毫不相關的問題中出現。

Fibonacci博弈

1、問題模型:

 有一堆個數為n的石子,遊戲雙方輪流取石子,滿足: 

(1)先手不能在第一次把所有的石子取完; 

(2)之後每次可以取的石子數介於1到對手剛取的石子數的2倍之間(包含1和對手剛取的石子數的2倍)。 約定取走最後一個石子的人為贏家。

2、解決思路:

  當n為Fibonacci數時,先手必敗。即存在先手的必敗態當且僅當石頭個數為Fibonacci數。 

    證明:根據“Zeckendorf定理”(齊肯多夫定理):任何正整數可以表示為若干個不連續的Fibonacci數之和。如n=83 = 55+21+5+2,我們看看這個分解有什麼指導意義:假如先手取2顆,那麼後手無法取5顆或更多,而5是一個Fibonacci數,那麼一定是先手取走這5顆石子中的最後一顆,同理,接下去先手取走接下來的後21顆中的最後一顆,再取走後55顆中的最後一顆,那麼先手贏。

    反證:如果n是Fibonacci數,如n=89:記先手一開始所取的石子數為y

    (1)若y>=34顆(也就是89的向前兩項),那麼一定後手贏,因為89-34=55=34+21<2*34。

    (2)y<34時剩下的石子數x介於55到89之間,它一定不是一個Fibonacci數,把x分解成Fibonacci數:x=55+f[i]+…+f[j],若,如果f[j]<=2y,那麼對B就是面臨x局面的先手,所以根據之前的分析,後手只要先取f[j]個即可,以後再按之前的分析就可保證必勝。

6、應用:

(1)可選步數為1-m的連續整數,直接取模即可,SG(x) = x % (m+1); 

(2)可選步數為任意步,SG(x) = x; 

(3)可選步數為一系列不連續的數,用mex(計算每個節點的值) 

7、練習:hdoj 1847 1536 3980

參考:

http://blog.csdn.net/lgdblue/article/details/15809893