1. 程式人生 > >博弈論知識入門

博弈論知識入門

(收集於網路)

博弈論是二人或多人在平等的對局中各自利用對方的策略變換自己的對抗策略,達到取勝目標的理論。博弈論是研究互動決策的理論。博弈可以分析自己與對手的利弊關係,從而確立自己在博弈中的優勢,因此有不少博弈理論,可以幫助對弈者分析局勢,從而採取相應策略,最終達到取勝的目的。(摘自百度百科)

(一)巴什博奕(Bash Game)

只有一堆n個物品,兩個人輪流從這堆物品中取物,規定每次至少取一個最多取m個。最後取光者得勝

 

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

    這個遊戲還可以有一種變相的玩法:兩個人輪流報數,每次至少報一個,最多報十
個,誰能報到100者勝。


巴什博弈博弈論裡面最簡單的一種形式。以下題目利用巴什博弈可以輕鬆解決:

1. http://acm.hdu.edu.cn/showproblem.php?pid=1846 (brave game)

2. http://acm.hdu.edu.cn/showproblem.php?pid=2147 (kiki's game)

3. http://acm.hdu.edu.cn/showproblem.php?pid=2149

 (public sale)

4. http://acm.hdu.edu.cn/showproblem.php?pid=2188 (選拔志願者)

 

下面介紹分析此類題目的通用方法:P/N分析:

P點: 即必敗點,某玩家位於此點,只要對方無失誤,則必敗;

N點: 即必勝點,某玩家位於此點,只要自己無失誤,則必勝。

三個定理:

定理:

     一、 所有終結點都是必敗點P(上游戲中,輪到誰拿牌,還剩0張牌的時候,此人就輸了,因為無牌可取);

    二、所有一步能走到必敗點P的就是N點;

    三、通過一步操作只能到N點的就是P點;

如:

 

Subtraction Games:

subtraction set S = {1, 3, 4}

 

 

x :   0 1 2 3 4 5 6 7 8 9 10 11 12 13 14…

Pos: P N P N N N N P N P N N  N N P…

 

 

以上題目均可以通過P/N分析法來解決。

這幾個題目都非常的簡單。下面僅對2149做簡單分析:(P/N分析也可以)

       首先明確使用巴什博弈有個前提(特點)每次拿的數量是從1-m的不間斷整數開始的。注意這一點很重要。無此條件巴什博弈不成立!

       其實這個題目稍微動動腦就可以把它轉換為巴什博弈(特點明顯)。你就假設兩人拍賣的時候是從給定的最高價開始—誰先拍賣到0誰就就是勝者。需要注意的是我們對特殊情況的考慮。

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

 

 

 

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

 

 

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

 

 

2)之後每次可以取的石子數介於1到對手剛取的石子數的2倍之間(包含1和對手剛取的石子數的2倍)。

 

 

 

約定取走最後一個石子的人為贏家,求必敗態。

 

 

這個和之前的Wythoff’s Game 和取石子游戲 有一個很大的不同點,就是遊戲規則的動態化。之前的規則中,每次可以取的石子的策略集合是基本固定的,但是這次有規則2:一方每次可以取的石子數依賴於對手剛才取的石子數。

 

 

這個遊戲叫做Fibonacci Nim,肯定和Fibonacci數列:f[n]:1,2,3,5,8,13,21,34,55,89,… 有密切的關係。如果試驗一番之後,可以猜測:先手勝當且僅當n不是Fibonacci數。換句話說,必敗態構成Fibonacci數列。

 

 

就像“Wythoff博弈”需要“Beatty定理”來幫忙一樣,這裡需要藉助“Zeckendorf定理”(齊肯多夫定理):任何正整數可以表示為若干個不連續的Fibonacci數之和。定理的證明可以在這裡 看到,不過我覺得更重要的是自己動手分解一下。

 

 

比如,我們要分解83,注意到83被夾在55和89之間,於是把83可以寫成83=55+28;然後再想辦法分解28,28被夾在21和34之間,於是28=21+7;依此類推 7=5+2,故 ;

 

 

如果n=83,我們看看這個分解有什麼指導意義:假如先手取2顆,那麼後手無法取5顆或更多,而5是一個Fibonacci數,如果猜測正確的話,(面臨這5顆的先手實際上是整個遊戲的後手)那麼一定是先手取走這5顆石子中的最後一顆,而這個我們可以通過第二類歸納法來繞過,同樣的道理,接下去先手取走接下來的後21顆中的最後一顆,再取走後55顆中的最後一顆,那麼先手贏。

 

 

反過來如果n是Fibonacci數,比如n=89:記先手一開始所取的石子數為y,若y>=34顆(也就是89的向前兩項),那麼一定後手贏,因為89-34=55=34+21<2*34,所以只需要考慮先手第一次取得石子數y<34的情況即可,所以現在剩下的石子數x介於55到89之間,它一定不是一個Fibonacci數,於是我們把x分解成Fibonacci數:x=55+f[i]+…+f[j],若,如果f[j]<=2y,那麼對B就是面臨x局面的先手,所以根據之前的分析,B只要先取f[j]個即可,以後再按之前的分析就可保證必勝。

 

 

下證:f[j]<=2y

 

 

反證法:假設f[j]>2y,則 y < f[j]/2 = (f[j-1] + f[j-2])/2 < f[j-1]

 

 

而最初的石子數是個斐波那契數,即 f[k]=x+y < f[k-1]+f[i]+…+f[j]+f[j-1] <= f[k-1]+f[i]+f[i-1] <= f[k-1]+f[k-2] <= f[k] (注意第一個不等號是嚴格的,矛盾!)

http://acm.nyist.net/JudgeOnline/problem.php?pid=135

http://acm.hdu.edu.cn/showproblem.php?pid=2516

(轉)分析:      
 n = 2時輸出second;     
 n = 3時也是輸出second; 
 n = 4時,第一個人想獲勝就必須先拿1個,這時剩餘的石子數為3,此時無論第二個人如何取,第一個人都能贏,輸出first; 
 n = 5時,first不可能獲勝,因為他取2時,second直接取掉剩下的3個就會獲勝,當他取1時,這樣就變成了n為4的情形,所以輸出的是second;   
 n = 6時,first只要去掉1個,就可以讓局勢變成n為5的情形,所以輸出的是first;      
 n = 7時,first取掉2個,局勢變成n為5的情形,故first贏,所以輸出的是first;     
 n = 8時,當first取1的時候,局勢變為7的情形,第二個人可贏,first取2的時候,局勢變成n為6得到情形,也是第二個人贏,取3的時候,second直接取掉剩下的5個,所以n = 8時,輸出的是second;    
 …………      
 從上面的分析可以看出,n為2、3、5、8時,這些都是輸出second,即必敗點,仔細的人會發現這些滿足斐波那契數的規律,可以推斷13也是一個必敗點。     
 藉助“Zeckendorf定理”(齊肯多夫定理):任何正整數可以表示為若干個不連續的Fibonacci數之和。n=12時,只要誰能使石子剩下8且此次取子沒超過3就能獲勝。因此可以把12看成8+4,把8看成一個站,等價與對4進行"氣喘操作"。又如13,13=8+5,5本來就是必敗態,得出13也是必敗態。也就是說,只要是斐波那契數,都是必敗點。
所以我們可以利用斐波那契數的公式:fib[i] = fib[i-1] + fib[i-2],只要n是斐波那契數就輸出second。

 

 

 

(三)威佐夫博奕(Wythoff Game)

兩堆各若干個物品,兩個人輪流從某一堆或同時從兩堆中取同樣多的物品,規定每次至少取一個,多者不限,最後取光者得勝。


    這種情況下是頗為複雜的。我們用(ak,bk)(ak ≤ bk ,k=0,1,2,…,n)表示兩堆物品的數量並稱其為局勢,如果甲面對(0,0),那麼甲已經輸了,這種局勢我們稱為奇異局勢。前幾個奇異局勢是:(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+√5)/2],bk= ak + k  (k=0,1,2,…,n 方括號表示取整函式)
奇妙的是其中出現了黃金分割數(1+√5)/2 = 1。618…,因此,由ak,bk組成的矩形近似為黃金矩形,由於2/(1+√5)=(√5-1)/2,可以先求出j=[a(√5-1)/2],若a=[(1+√5)/2],那麼a = aj,bj = aj + j,若不等於,那麼a = aj+1,bj+1 = aj+1+ j + 1,若都不是,那麼就不是奇異局勢。然後再按照上述法則進行,一定會遇到奇異局勢。

http://acm.nyist.net/JudgeOnline/problem.php?pid=161

 

 

 

(三)尼姆博奕(Nimm Game)

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

    這種情況最有意思,它與二進位制有密切關係,我們用(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)即可。

    例1。(14,21,39),14(+)21=27,39-27=12,所以從39中拿走12個物體即可達到奇異局勢(14,21,27)。

    例2。(55,81,121),55(+)81=102,121-102=19,所以從121中拿走19個物品
就形成了奇異局勢(55,81,102)。

    例3。(29,45,58),29(+)45=48,58-48=10,從58中拿走10個,變為(29,4
5,48)。

下面先是一道簡單的尼姆博弈題目

http://acm.hdu.edu.cn/showproblem.php?pid=1850

只要運用上面的知識即可解決(具體細節見程式碼)


 

 

然而這並不是博弈的重點,LCY老師講到博弈之王道乃是SG值(具體見 http://acm.hdu.edu.cn/forum/read.php?tid=6875)。

SG值:一個點的SG值就是一個不等於它的後繼點的SG的且大於等於零的最小整數。

我的理解:在步驟允許的情況下,與前面一個必敗點的差(也就是說這個差是規定的、能走的、其中一個步數)!
後繼點:也就是按照題目要求的走法(比如取石子可以取的數量,方法)能夠走一步達到的那個點。(sg值的理解很抽象。我的隊友mo、xi說多畫畫就可以了)
現在我們拿http://acm.hdu.edu.cn/showproblem.php?pid=1847這道題分析一下。

我們列舉下牌數為2-10的sg值:(SG(x)=mex{SG(x-S[i])}。)

num: 2     3     4     5     6     7     8     9     10 

sg值: 2     0     1      2     0     1     2     0      1

具體的程式碼如下:(當然這題用P/N分析要簡單得多,這裡僅理解sg值)

 

[cpp] view plaincopy

  1. #include<cstdio>  
  2. #include<algorithm>  
  3. using namespace std;  
  4. #define N 1000+10  
  5.   
  6. int arr[11],sg[N];  
  7.   
  8. int pre()//把1000以內的所有的可能一次拿的牌都算出來!   
  9. {  
  10.     arr[0]=1;  
  11.     for(int i=1;i<=10;i++) arr[i]=arr[i-1]*2;  
  12.     return 0;  
  13. }  
  14.   
  15. int mex(int x)//這是求解改點的sg值的演算法函式(採用記憶化搜尋)   
  16. {  
  17.     if(sg[x]!=-1) return sg[x];  
  18.     bool vis[N];  
  19.     memset(vis,false,sizeof(vis));  
  20.     for(int i=0;i<10;i++)  
  21.     {  
  22.         int temp=x-arr[i];  
  23.         if(temp<0) break;  
  24.         sg[temp]=mex(temp);  
  25.         vis[sg[temp]]=true;  
  26.     }  
  27.     for(int i=0;;i++)  
  28.     {  
  29.         if(!vis[i])  
  30.         {  
  31.             sg[x]=i; break;  
  32.         }  
  33.     }  
  34.     return sg[x];  
  35. }  
  36.   
  37. int main()  
  38. {  
  39.     freopen("game.in","r",stdin); freopen("game.out","w",stdout);  
  40.     int num;  
  41.     pre();  
  42.     while(scanf("%d",&num)!=EOF)  
  43.     {  
  44.         memset(sg,-1,sizeof(sg));  
  45.         if(mex(num)) printf("Kiki/n");    
  46.         else printf("Cici/n");   
  47.     }  
  48.     return 0;  
  49. }  
  50.           

 

(五)取火柴遊戲

題目1:今有若干堆火柴,兩人依次從中拿取,規定每次只能從一堆中取若干根,可將一堆全取走,但不可不取,最後取完者為勝,求必勝的方法。 

題目2:今有若干堆火柴,兩人依次從中拿取,規定每次只能從一堆中取若干根,可將一堆全取走,但不可不取,最後取完者為負,求必勝的方法。

題目1 :尼姆博奕(Nimm Game)

題目2 :  先者必敗條件: 奇異局勢&& 充裕堆數目>=2   或者  非奇異局勢&& 孤單堆數目==n

 

詳解:點選博弈知識彙總

 

推薦HDOJ題目

http://acm.hdu.edu.cn/showproblem.php?pid=1907

http://acm.hdu.edu.cn/showproblem.php?pid=2509

 

 


主要是後繼點和SG值的問題:
SG值:一個點的SG值就是一個不等於它的後繼點的SG的且大於等於零的最小整數。
後繼點:也就是按照題目要求的走法(比如取石子可以取的數量,方法)能夠走一步達到的那個點。
具體的有關SG值是怎麼運用的希望大家自己多想想。
課件後面有一個1536的程式碼。可以放在後面做做
看到這裡推薦大家做幾道題:1846(最簡單的博弈水題)
1847(求SG值)

有了上面的知識接下來我們來看看組合博弈(n堆石子)

推薦大家看個資料:
博弈-取石子游戲(推薦等級五星級)
http://acm.hdu.edu.cn/forum/read.php?fid=20&tid=5748
http://hi.baidu.com/netnode/blog/item/30932c2edc7384514fc226ea.html
這裡提出了一個奇異狀態的問題。看了這篇文章你會發現異或運算在博弈中使用的妙處。當然這裡指出的只是組合博弈中一種特殊情況。
王道還是對SG值的求解,但是知道這麼一種思路無疑對思維的廣度和深度擴充套件是很有幫助的。
ZZ博弈
http://acm.hdu.edu.cn/forum/read.php?fid=9&tid=10617
這裡介紹了組和博弈的兩種大的型別,一種是最後取的是N狀態一種是最後取的是P狀態,兩個狀態的解題方法能看懂很有幫助。當然,能夠把推導過程理解,吃透無疑是大牛級的做法~小子也佩服的緊~   
    1536題推薦做做這題,這題前面提醒大家是一個求SG值的題目,題目前面是對異或運算運用在組合博弈問題中的很好的解釋。當然題目本身是有所不同的。因為在這裡面對取法有所要求。那麼這樣就回歸到了解決博弈問題的王道演算法——求SG值上。
    有關運用求SG值的博弈題目有: 1850(也可基於奇異狀態異或)
1848(中和的大斐波那契數列的典型求SG值題)
1517(個人認為有點猥瑣的題目。。。。在此題上困擾很久。當然搞出來很開心。小子是用比較規矩的求SG值的方法求出來的,但是論壇有人對其推出來了規律,這裡佩服一下,大家可以學習一下)
1079(更猥瑣的題目,對新手要求較高,因為按傳統方法需要比較細緻的模擬加對邊角狀態的考慮,同樣有人推出來了公式)
當你全部看完以上的東西。做完以上的題目的話。。。小子恭喜你~你博弈入門了~~~~
    這裡小子告訴大家。博弈很強大。學習要耐心~謝謝
Current System Time : 2008-12-11 19:16:03

ACM課作業:
1001 Brave Game
1002 Good Luck in CET-4 Everybody!
1003 Fibonacci again and again
1004 Rabbit and Grass
1005 Being a Good Boy in Spring Festival
1006 Public Sale 
1007 悼念512汶川大地震遇難同胞——選拔志願者 
1008 kiki’s game 
1009 Calendar Game 
1010 A Multiplication Game 
1011 Digital Deletions 
1012 S-Nim
http://acm.hdu.edu.cn/forum/read.php?tid=11339&fpage=0&toread=&page=1

(四)最後我們來看組合博弈:(博弈的精華)

博弈-取石子游戲

http://acm.hdu.edu.cn/forum/read.php?fid=20&tid=5748
http://hi.baidu.com/netnode/blog/item/30932c2edc7384514fc226ea.html

組合博弈無疑是對sg值的熟練操作例如:有n堆石子,每次可以從第1堆石子裡取1顆、2顆或3顆,可以從第2堆石子裡取奇數顆,可以從第3堆及以後石子裡取任意顆…… 我們可以把它看作3個子遊戲,第1個子遊戲只有一堆石子,每次可以取1、2、3顆,很容易看出x顆石子的局面的SG值是x%4。第2個子遊戲也是隻有一堆 石子,每次可以取奇數顆,經過簡單的畫圖可以知道這個遊戲有x顆石子時的SG值是x%2。第3個遊戲有n-2堆石子,就是一個Nim遊戲。對於原遊戲的每 個局面,把三個子游戲的SG值異或一下就得到了整個遊戲的SG值,然後就可以根據這個SG值判斷是否有必勝策略以及做出決策了。其實看作3個子遊戲還是保 守了些,乾脆看作n個子遊戲,其中第1、2個子遊戲如上所述,第3個及以後的子游戲都是“1堆石子,每次取幾顆都可以”,稱為“任取石子游戲”,這個超簡單的遊戲有x顆石子的SG值顯然就是x。