博弈論 Nim遊戲與SG函式

2021-07-14 16:13:08 字數 4004 閱讀 3290

普通nim遊戲:

有若干堆石子,兩人輪流從中取石子,取走最後乙個石子的人為勝利者

我們判斷先手必勝還是先手必敗就要判斷先手面對的局面是必勝態還是必敗態

並且普通nim遊戲滿足以下性質:

1.無法移動的狀態是必敗態

2.可以移動到必敗態的局面一定是非必敗態

3.在必敗態做所有操作的結果都是非必敗態

這些性質很好理解,就不予以證明了

接下來分析什麼情況下是必敗態

在普通nim遊戲中,a1^a2^a3^……^an=0是必敗態

以下是證明:

從最簡單的說起,若先手面對的是0 0 0 0 0 0這種局面,那麼先手必敗(xor為0 )

如果a1^a2^……^ai^……^an=0,那麼一定不存在某個合法操作使得ai變為ai』後依然滿足a1^a2^……^ai』^……^an=0,因為xor滿足消除性質,所以可以得出a1^a2^……^ai^……^an=0=a1^a2^……^ai』^……^an==>ai=ai』

所以如果先手面對的時xor=0的情況,先手必敗,反之先手必勝

但是如果遊戲變得稍微複雜一點,比如我規定了第一堆中只能取一顆,第二堆中只能取奇數課顆……這可怎麼辦呀———-鏘鏘鏘鏘!!!sg函式出場

sg函式全稱為sprague-grundy 函式

現在我們來研究乙個看上去似乎更為一般的遊戲:給定乙個有向無環圖和乙個起始頂 點上的一枚棋子,兩名選手交替的將這枚棋子沿有向邊進行移動,無法移動者判負。事實上,這個遊戲可以認為是所有impartial combinatorial games(也就是nim遊戲)的抽象模型。也就是說,任何乙個icg都可以通過把每個局面看成乙個頂點,對每個局面和它的子局面連一條有向邊來抽象成這個「有向圖遊戲」。下 面我們就在有向無環圖的頂點上定義sprague-garundy函式。

首先定義mex(minimal excludant)運算,表示最小的不屬於這個集合的非負整數。例如mex=3、mex=0、mex{}=0。

sg(x)=mex,其實就是狀態x能轉移到y

對於所有的出度為0的點他們的sg函式都等於0,因為其後繼集合為空集,對於每乙個sg值為0的點,其後繼中一定滿足sg(y)!=0,對於每乙個sg值不為0的點,其後繼中一定存在乙個sg(y)=0

以上的結論表明sg=0的點對應的是必敗態,我們通過計算有向無環圖每個頂點的sg值就可以找到必勝的策略

如果問題在複雜一點呢(⊙o⊙)…

讓我們再來考慮一下頂點的sg值的意義。當g(x)=k時, 表明對於任意乙個0<=i< k,都存在x的乙個後繼y滿足g(y)=i。也就是說,當某枚棋子的sg值是k時,我們可以把它變成0、變成 1、……、變成k-1,但絕對不能保持k不變。不知道你能不能根據這個聯想到nim遊戲,nim遊戲的規則就是:每次選擇一堆數量為k的石子,可以把它變 成0、變成1、……、變成k-1,但絕對不能保持k不變。這表明,如果將n枚棋子所在的頂點的sg值看作n堆相應數量的石子,那麼這個nim遊戲的每個必 勝策略都對應於原來這n枚棋子的必勝策略。

所以我們可以證明當選手處於必敗態時,所有棋子所在節點的sg值xor=0

所 以我們可以定義有向圖遊戲的和(sum of graph games):設g1、g2、……、gn是n個有向圖遊戲,定義遊戲g是g1、g2、……、gn的和(sum),遊戲g的移動規則是:任選乙個子遊戲gi 並移動上面的棋子。就可以得到以下式子:sg(g)=sg(g1)^sg(g2)^…^sg(gn)。

如果你看了以上一堆證明感覺頭大的話,我們來換一種小清新萌萌噠的證明方法:

考慮乙個經常會遇到的問題:兩個遊戲的和。有兩個遊戲a和b,兩個人玩,每個人每輪可以操作其中乙個,但不能不操作,兩個遊戲都變為空集時輸。

定義運算子+

a + b = ∪

這是個遞迴定義。

於是我們來考慮sg(a + b)

容易知道:

sg(a + b) = mex( ∪ )

現在到了這裡,大膽猜想吧……

經過數學家的一番折騰,發現sg(a + b) = sg(a) ^ sg(b)

其中x ^ y指x和y的異或值。

然後來考慮複雜問題:

取石子問題,有1堆n個的石子,每次只能取個石子,先取完石子者勝利,那麼各個數的sg值為多少?

sg[0]=0,f=,

x=1時,可以取走1-f個石子,剩餘個,mex=,故sg[1]=1;

x=2時,可以取走2-f個石子,剩餘個,mex=,故sg[2]=0;

x=3時,可以取走3-f個石子,剩餘個,mex=,故sg[3]=1;

x=4時,可以取走4-f個石子,剩餘個,mex=,故sg[4]=2;

x=5時,可以取走5-f個石子,剩餘個,mex=,故sg[5]=3;

以此類推…..

x 0 1 2 3 4 5 6 7 8….

sg[x] 0 1 0 1 2 3 2 0 1….

好暈啊+_+ t_t

不管了,反正我們可以得出以下性質

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

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

3.可選步數為一系列不連續的數,用getsg()計算

例題:bzoj 1874

如果先手必勝則sgaixor!=0

否則先手必敗,如果要知道第一步操作就暴力列舉

**如下:

#include

#include

#include

#include

using

namespace

std;

const

int maxn=1000+5;

int n,m,a[10+5],b[10+5],sg[maxn],vis[10+5];

void getsg(int n)

}}inline

int read()

while(ch>='0'&&ch<='9')

x=x*10+ch-'0',ch=getchar();

return f*x;

}signed main(void)

for(int i=1;i<=n;i++)

}}

anti-nim bzoj 1022

小約翰經常和他的哥哥玩乙個非常有趣的遊戲:桌子上有n堆石子,小約翰和他的哥哥輪流取石子,每個人取的時候,可以隨意選擇一堆石子,在這堆石子中取走任意多的石子,但不能一粒石子也不取,我們規定取到最後一粒石子的人算輸。小約翰相當固執,他堅持認為先取的人有很大的優勢,所以他總是先取石子,而他的哥哥就聰明多了,他從來沒有在遊戲中犯過錯誤。小約翰一怒之前請你來做他的參謀。自然,你應該先寫乙個程式,**一下誰將獲得遊戲的勝利。

分析:

我們首先考慮最簡單的情況–全都是1

如果有奇數堆,顯然先手必敗

偶數堆先手必勝

然後考慮下一種情況:

1 1 1 1 1 ……>1

先手必勝,為什麼呢

如果前面有奇數個1,那麼先手吧最後一堆取完,變成奇數個1,則後手必敗

如果前面有偶數個1,那麼先手把最後一堆取為1個,變成奇數堆1,後手必敗

在這種情況下,sg函式也就是xor和≠0,先手必勝

如果能夠保證每次先手取完之後xor=0那麼先手必勝(因為後手不管怎麼去sg函式一定不等於0,最後一定可以取乘1 1 1 1……>1的形式)

**如下:

#include

#include

#include

#include

using

namespace

std;

const

int maxn=5000+5;

int cas,n,cnt,flag,ans;

inline

int read()

while(ch>='0'&&ch<='9')

x=x*10+ch-'0',ch=getchar();

return f*x;

}signed main(void)

if(flag)

博弈論之NIM遊戲與SG函式

恩,本文會簡要介紹一下nim取石子遊戲與sg函式,並附上一些有趣的例題。首先,讓我們來看一看最簡單的取石子遊戲。遊戲1 規則 有x個石子,兩人輪流取,最多取y個,不能不取,沒得取的人輸,兩個人都按照最優策略進行遊戲,問先手必勝的充要條件。答案 x mod y 1 0 恩,剛才那個遊戲很簡單,下面讓我...

博弈論 Nim博弈 反Nim博弈 SG函式

nim遊戲 hdu1846 若各堆石子異或和為不為零,則先手勝 後手當且僅當異或和為零時取勝 此題問要想先手取勝第一步的取法,考慮到上述引理,只需遍歷一遍石子找到異或和的最高位匹配的個數。int a 105 int main return0 view code hdu 1848 在上題的基礎上取法只...

博弈論 SG和NIM

感覺博弈論acm還蠻經常考,現在我只記得nim結論似乎不太行 博弈論就是要靜下心一口氣先把概念看完才懂啊 所以建議找個時間一口其總結完 參考了nim遊戲屬於 impartial combinatorial games 以下簡稱icg 滿足以下條件的遊戲是icg 可能不太嚴謹 1 有兩名選手 2 兩名...