巴什博弈 (bash game)
題型
僅有一堆n個物品,兩我的輪流取1~m個,最後取的人勝(不能取的人輸)html
分析
整體可分幾種狀況數組
- $n=0$,先手輸
- $0<n<=m$,先手勝
- $n=m+1$,先手輸
- $n=k*(m+1)+r$,先手勝(先手取走r個,給後手留下k*(m+1)的局面)
- $n=k*(m+1)$,先手輸
代碼
int Bash_Game(int n,int m) //是否先手有必贏策略
{
if(n==0) return 0;
if(n%(m+1)!=0) return 1;
return 0;
}
尼姆博弈(Nim Game)
題型
將一堆變爲多堆;
即:
有3堆各若干個物品,兩我的輪流從某一堆取任意多的物品,規定每次至少取1個,多者不限,最後取光者得勝。bash
分析
本部分含其餘博客內容markdown
地址:https://www.cnblogs.com/jiangjun/archive/2012/11/01/2749937.htmlapp
- 首先本身想一下,就會發現只要最後剩兩堆物品同樣多(不爲零),第三堆爲零,那面對這種局勢的一方就必敗
- 那咱們用(a,b,c)表示某種局勢,首先(0,0,0)顯然是必敗態,不管誰面對(0,0,0) ,都必然失敗;第二種必敗態是(0,n,n),本身在某一堆拿走k(k ≤ n)個物品,不論k爲多少,對方只要在另外一堆拿走k個物品,最後本身都將面臨(0,0,0)的局勢,必敗。仔細分析一下,(1,2,3)也是必敗態,不管本身如何拿,接下來對手均可以把局勢變爲(0,n,n)的情形
- 那這種奇異局勢有什麼特色呢?
也不知誰這麼牛逼,居然能把這種局勢和二進制聯繫在一塊兒
這裏說一種運算符號,異或’^’,a^b=a’b+ab’(a’爲非a)
咱們用符號XOR表示這種運算,這種運算和通常加法不一樣的一點是1 XOR 1 = 0。先看(1,2,3)的按位模2加的結果:
1 = 二進制01
2 = 二進制10
3 = 二進制11 XOR
———————
0 = 二進制00 (注意不進位)
- 對於奇異局勢(0,n,n)也同樣,結果也是0
任何奇異局勢(a,b,c)都有a XOR b XOR c = 0
- 若是咱們面對的是一個非必敗態(a,b,c),要如何變爲必敗態呢?
假設 a < b < c,咱們只要將 c 變爲a XOR b,便可。由於有以下的運算結果:
a XOR b XOR (a XOR b)=(a XOR a) XOR (b XOR b) = 0 XOR 0 = 0
要將c 變爲a XOR b,只要對 c進行 c-(a XOR b)這樣的運算便可
-
尼姆博弈模型能夠推廣到:有n堆若干個物品,兩我的輪流從某一堆取任意多的物品,規定每次至少取一個,多者不限,最後取光者得勝。
這個遊戲中的變量是堆數k和各堆的物品數N1,N2,……,Nk。
對應的組合問題是,肯定先手獲勝仍是後手獲勝以及兩個遊戲人應該如何取物品才能保證本身獲勝
spa
-
爲了進一步理解Nim取物品遊戲,咱們看看特殊狀況。
若是遊戲開始時只有一堆物品,先手則經過取走全部的物品而獲勝。如今設有2堆物品,且物品數量分別爲N1和N2。遊戲者取得勝利並不在於N1和N2的值具體是多少,而是取決於它們是否相等。code
- 也就說兩堆的策略咱們有了,如今咱們如何從兩堆的取子策略擴展到任意堆數中呢?
- 首先回憶一下,每一個正整數都有對應的一個二進制數,例如:57(10) = 111001(2) ,即:57(10)=25+24+23+20。因而,咱們能夠認爲每一堆物品數由2的冪數的子堆組成。這樣,含有57枚物品大堆就能當作是分別由數量爲2五、2四、2三、20的各個子堆組成
- 如今考慮各大堆大小分別爲N1,N2,……Nk的通常的Nim博弈。將每個數Ni表示爲其二進制數(數的位數相等,不等時在前面補0):
N1 = as…a1a0
N2 = bs…b1b0
……
Nk = ms…m1m0
若是每一種大小的子堆的個數都是偶數,咱們就稱Nim博弈是平衡的,而對應位相加是偶數的稱爲平衡位,不然稱爲非平衡位。所以,Nim博弈是平衡的,當且僅當:
as +bs + … + ms 是偶數,即as XOR bs XOR … XOR ms = 0
……
a1 +b1 + … + m1 是偶數,即a1 XOR b1 XOR … XOR m1 = 0
a0 +b0 + … + m0是偶數,即a0 XOR b0 XOR … XOR m0 = 0
- 因而,咱們就能得出尼姆博弈中先手獲勝策略:
Bouton定理:先手可以在非平衡尼姆博弈中取勝,然後手可以在平衡的尼姆博弈中取勝。即狀態(x1, x2, x3, …, xn)爲P狀態當且僅當x1 xor x2 xor x3 xor … xor xn =0。這樣的操做也稱爲Nim和(Nim Sum)
咱們以一個兩堆物品的尼姆博弈做爲試驗。設遊戲開始時遊戲處於非平衡狀態。這樣,先手就能經過一種取子方式使得他取子後留給後手的是一個平衡狀態下的遊戲,接着不管後手如何取子,再留給先手的必定是一個非平衡狀態遊戲,如此反覆進行,當後手在最後一次平衡狀態下取子後,先手便能一次性取走全部的物品而獲勝。而若是遊戲開始時遊戲牌平衡狀態,那根據上述方式取子,最終後手能獲勝
- 下面應用此獲勝策略來考慮4堆的Nim博弈。其中各堆的大小分別爲7,9,12,15枚硬幣。用二進制表示各數分別爲:0111,1001,1100和1111
因而可獲得以下一表:
|
$2^{3}=8$ |
$2^{2}=4$ |
$2^{1}=2$ |
$2^{0}=1$ |
大小爲7的堆 |
0 |
1 |
1 |
1 |
大小爲9的堆 |
1 |
0 |
0 |
1 |
大小爲12的堆 |
1 |
1 |
0 |
0 |
大小爲15的堆 |
1 |
1 |
1 |
1 |
由Nim博弈的平衡條件可知,此遊戲是一個非平衡狀態的Nim博弈,所以,先手在按獲勝策略必定可以取得最終的勝利。具體作法有多種,先手能夠從大小爲12的堆中取走11枚硬幣,使得遊戲達到平衡(以下表)htm
|
$2^{3}=8$ |
$2^{2}=4$ |
$2^{1}=2$ |
$2^{0}=1$ |
大小爲7的堆 |
0 |
1 |
1 |
1 |
大小爲9的堆 |
1 |
0 |
0 |
1 |
大小爲12的堆 |
0 |
0 |
0 |
1 |
大小爲15的堆 |
1 |
1 |
1 |
1 |
以後,不管後手如何取子,先手在取子後仍使得遊戲達到平衡
一樣的道理,先手也能夠選擇大小爲9的堆並取走5枚硬幣而剩下4枚,或者,先手從大小爲15的堆中取走13枚而留下2枚blog
- 歸根結底, Nim博弈的關鍵在於遊戲開始時遊戲處於何種狀態(平衡或非平衡)和先手是否可以按照取子游戲的獲勝策略來進行遊戲
代碼
int Nimm_Game(int n) //假設n個數存在數組f[]中,有必勝策略返回1
{
int sum=0;
for(int i=1;i<=n;i++)
sum^=f[i];
if(sum) return 1;
return 0;
}