暑期集訓 博弈論概覽

2022-07-24 05:18:06 字數 4341 閱讀 2789

tags: 暑期集訓 第一周 博弈論

目錄(二)nim game -- 尼姆博弈

例題nim遊戲變體之階梯nim博弈

例題(三)wythoff's game -- 威佐夫博弈

(四)sprague-grundy function -- sg函式

相關部落格1 - 組合遊戲 sg函式和sg定理

相關部落格2 - 博弈論 sg函式 sg定理

(五)沒有錯後面這麼簡潔就是因為我寫不下去了=-=

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

這是程式設計博弈題中最簡單的一類,我們知道當先手面對\(n=m+1\)的情況時,後手必勝。以此為基準向上推演我們可以得到如下結論:

當且僅當先手面對的物品個數 n 滿足 \(n=k(m+1)\) 時後手必勝。

因為設先手取 x 個物品,後手一定可以取到(m+1-x)個物品使物品總數變為\(n=(k-1)(m+1)\)。以此類推,可以發現最後一定能變成\(n=m+1\)的奇異情況。所以當\(n%(m+1)==0\)時後手必勝。與此對應,當\(n%(m+1)==k>0\)時,先手可以拿走k個物品讓對手面對\(n=k(m+1)\)的必敗情況。

1 - 悼念512汶川大**遇難同胞——選拔志願者 hdu - 2188

思路:

翻譯一下題目:石頭總數為\(n_\)元。所以直接判斷n%(m+1)即可

**:/*不被允許出現在第一列的井號*/ #includeusing namespace std;

int main() \)

思路:翻譯題目:兩個人 alice 和 bob 以偶數堆的石頭 \(a[n] (2≤n≤50, 1≤a_i<)\) 進行遊戲,每人每輪可從剩餘非空的 \(\frac\) 堆石頭中取出任意大於 1 數量的石頭,同一輪中不同堆中取出的石頭可以不相同。若輪到某人時非空石頭堆不足 \(\frac\) 則此人失敗。問在給定資料中誰必定獲勝。

本題中,誰先將任意一堆或擠兌==幾堆石頭取空,誰就輸了。因為對家接著取空\(\frac\)堆石頭,剩下的石頭堆數就不滿 \(\frac\)了。

什麼時候先手能保持不敗之地呢?設最少的石子堆a[i]的石子數為a,有b堆這樣的石子,當b<=n/2的時候,先手可以將另外一半的石子拿走至與前一半石子堆的數量一致( 變成 ) ,那麼接下來無論對方拿走多少石子,我們都可以模仿對方的策略,顯然,對方會先拿控一堆石子走到必敗態,那麼先手就必贏。在考慮一種情況,當b>n/2時,也就是最少的石子堆數量佔一半以上,那麼無論先手怎麼取,後手都可以將剩下的石子堆保持最少的石子堆有一半以上(無論對方怎麼取,我們只需要把n/2個石子堆數量保持與最小的一致),那麼此時先手是一定會先拿空一堆石子,那麼先手必敗。綜上,也就是判斷最少石子堆數量是否有一半以上即可。

**:/**/ #include/**/ #includeusing namespace std;

int main()

sort(a,a+n);

if(a[0] == a[n/2]) cout<<"bob"<

有\(n_\)堆石子,每堆石子的數量都是有限的,合法的移動是「選擇一堆石子並拿走若干顆(不能不拿)」,如果輪到某個人時所有的石子堆都已經被拿空了,則判負(因為他此刻沒有任何合法的移動)。

先給結論

令第 \(i\) 堆石子個數為 \(a_i\),當且僅當\(a_1\oplus a_2\oplus a_3 \oplus ...\oplus a_n=0\)時後手必勝

證明:

令 \(a_1\oplus a_2\oplus a_3 \oplus ...\oplus a_n\) 為m。

首先,第乙個先手必敗點就是所有石頭堆數目都為0,此時\(0\oplus 0\oplus 0\oplus ...\oplus 0=0\)。

其次證明兩點:

任何 \(m!=0\) 的情況都能通過一次操作變成 \(m=0\) 的情況。

任何 \(m=0\) 的情況都無法經過一次操作變成另乙個 \(m=0\) 的情況。

當 \(m=k_\) 時,設k的二進位制表示有 \(x\) 位。則一定有至少乙個 \(a_i\) ,其二進位制表示第 \(x\) 位同樣為1。

則有 \(a_i \oplus k,即 \(\exists m\gt 0使a_i-m=a_i\oplus k\) 。

又通過 \(x\oplus y \oplus y = x\) 可得:\(a_1\oplus a_2\oplus a_3 \cdots a_ \oplus a_ \cdots a_n=k\oplus a_i\)

所以 \(a_1\oplus a_2\oplus a_3 \cdots a_ \oplus a_ \cdots a_n\oplus (a_i-m)=k\oplus a_i\oplus (a_i-m)\)

即 \(a_1\oplus a_2\oplus a_3 \cdots a_ \oplus a_ \cdots a_n\oplus (a_i\oplus k)=k\oplus a_i\oplus (a_i\oplus k) = 0\)

1得證

當 \(m=0\) 時,設 \(\exists a_i^=a_i-m_, 使m^=a_1\oplus a_2\cdots a_i^\cdots \oplus a_n=0\)

則有 \(a_1\oplus a_2\cdots a_i^\cdots \oplus a_n=a_1\oplus a_2\cdots a_i\cdots \oplus a_n\)

即 \(a_i^=a_i\),則\(m=0\) 。可知 \(m=0\) 非法。所以2得證

1 - being a good boy in spring festival hdu - 1850

思路:

直接套公式計算\(n_1\oplus n_2 \cdots \oplus n_m\)即可

**:/**/#includeusing namespace std;

int main()

if(sum == 0) cout<<0<2 - northcott game hdu - 1730

思路:我認為博弈論有乙個很重要的點就是操作無效化。通過模仿對手的操作令部分操作無效化。使題目條件變得更簡單

對於這道題而言,我們只需考慮兩個棋子之間的空隙,將間隙dang'che即可。因為若先手棋子後退了,則後手只需要將自己的棋子平移相同距離即可。所以我們完全可以忽視兩邊的空間。且我們知道先手不能隨便後退,否則後手就有了改變局勢的機會。

於是我們計算每行兩顆棋子之間的空隙,並計算其異或和便能得出答案

**:

/**/#includeusing namespace std;

int main()

if(!sum)

cout<<"bad luck!"<

階梯nim博弈

有一n階樓梯,第\(i\)階樓梯上有\(a_i\)枚硬幣。兩個人輪流操作。每次操作可將第\(i\)階台階上的\(m_\)枚硬幣移動到第\(i-1\)階台階。問先手必勝情況。

在本類nim變體中,我們發現,對於一種情況的先手a而言,若a從第\(2k\)級台階移動\(m\)枚硬幣到第\(2k-1\)級台階,後手b則可緊跟著將這m枚硬幣從第\(2k-1\)級台階移動到第\(2k-2\)級台階。即先手對偶數級台階進行操作,最後一定是後手將其放到地面。先手永遠不可能將偶數級台階的硬幣親手放到地面去。由此我們可以忽視任何對偶數級台階的操作,將奇數級台階的硬幣移動到偶數級台階便視為這些硬幣已經被「拿走」。僅考慮奇數級台階。這個問題就變成了普通nim問題。我們只需要計算奇數階硬幣數的異或和\(a_1 \oplus a_3 \oplus \cdots \oplus a_1)}\)即可。

3 - georgia and bob poj - 1704

思路:將兩個棋子之間的空隙看成石頭。左邊是樓梯頂右邊是樓梯底。這道題就變成了階梯nim博弈

**:/**/#include/**/#include/**/#includeusing namespace std;

int main() ;

int sum = 0;

while(t--)

sort(p+1,p+n+1);

int i=1;

if(n%2) i=0;

for(i;i<=n;i+=2)

if(sum) cout<<"georgia will win"《有兩堆石子\(m,n(m>0,n>0)\),雙方輪流取走一些石子,合法的取法有如下兩種:

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

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

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

很喜歡這篇部落格,個人認為有很大的提點作用。博主同樣也是轉的,原部落格位址進不去了。

博弈論 Nim博弈

1.nim博弈的起源很早,至於歷史我們就不再說了,直接說它的使用場景。1 依舊是兩個人博弈,但是物品時n堆,每一堆有ai個。2 每個人可以挑選一堆取走若干個,但是不能不取。3 最先取完所有物品的人獲勝。4 結論 所以堆的物品的數量異或起來是0,先手必敗。2.乙個nim博弈的例項 nim博弈。乍一看這...

博弈論 博弈混合

給你乙個n m的棋盤,然後給你4種棋子,分別是 1.王 能橫著走,或者豎著走,或者斜著走,每次可以走1格 2.車 可以橫著走或者豎著走,每次可以走無數格 3.馬 走日字形,例如 如果現在在 1,1 可以走到 2,3 即先走一格直線,然後斜著走一格 4.王后 可以橫著走,或者豎著走,或者斜著走,每次可...

Nim博弈(博弈論)

1.題目 給定n堆石子,兩位玩家輪流操作,每次操作可以從任意一堆石子中拿走任意數量的石子 可以拿完,但不能不拿 最後無法進行操作的人視為失敗。問如果兩人都採用最優策略,先手是否必勝。思路 必勝狀態 a1 a2 an 0 可以走到某乙個必敗狀態 必敗狀態 a1 a2 an 0 走不到任何乙個必敗狀態 ...