【博弈论】威佐夫博弈
簡介
威佐夫博弈( W y t h o f f G a m e Wythoff\ Game Wythoff?Game):有兩堆物品個數是 n n n和 m m m,甲乙兩個人輪流從一堆選取 k k k個物品或兩堆中選取各選取 k k k個物品,最后取完物品的人獲勝。
思路
兩堆物品數用 ( n , m ) (n,m) (n,m)表示,滿足 n ≤ m n\le m n≤m,如果 n > m n>m n>m則交換 n n n與 m m m。
現考慮各種狀態,發現先手必輸態如下:
當 n = 0 n=0 n=0時,
( 0 , 0 ) (0,0) (0,0)沒有物品甲必敗,
( 0 , m ≠ 0 ) (0,m\ne 0) (0,m?=0)有物品甲必勝。
當 n = 1 n=1 n=1時,
( 1 , 2 ) (1,2) (1,2)會變成乙選 ( 0 , 1 ) (0,1) (0,1), ( 0 , 2 ) (0,2) (0,2)或 ( 1 , 1 ) (1,1) (1,1),甲必敗,
( 1 , m ≠ 2 ) (1,m\ne 2) (1,m?=2)有物品甲必勝利。
當 n = 2 n=2 n=2時,
( 2 , m ) (2,m) (2,m)變成乙選 ( 0 , 2 ) (0,2) (0,2)或 ( 1 , 2 ) (1,2) (1,2),甲必勝。
當 n = 3 n=3 n=3時,
( 3 , 5 ) (3,5) (3,5)甲必敗,
( 3 , m ≠ 5 ) (3,m\ne 5) (3,m?=5)甲必勝。
進一步推算可以發現所有的先手必敗局為 ( 0 , 0 ) (0,0) (0,0), ( 1 , 2 ) (1,2) (1,2), ( 3 , 5 ) (3,5) (3,5), ( 4 , 7 ) (4,7) (4,7), ( 6 , 10 ) … (6,10)\dots (6,10)…
這種先手必敗局叫做奇異局勢,可以發現第 k k k項的 n n n是前 k ? 1 k-1 k?1項中未出現的最小正整數 i i i,而 m = i + k m=i+k m=i+k。
每個人要想獲勝就是盡量使對方變成奇異局勢。
根據相關資料可以得知第 k k k項奇異局勢的 n k = k ( ( 5 ) + 1 ) 2 , m k = n k + k n_k=\frac{k(\sqrt(5)+1)}{2},m_k=n_k+k nk?=2k((?5)+1)?,mk?=nk?+k。
bool Wythoff(int n,int m){//判斷先手且為n,m時是否取勝 if(n>m) return Wythoff(m,n);//保證n<=m int k=m-n;//計算出項數k int _n=k*(sqrt(5)+1)/2.0;//計算出必敗時的n return n!=_n;//判斷是否必敗 }例題
hdu1527
題目描述
有兩堆石子,數量任意,可以不同。游戲開始由兩個人輪流取石子。游戲規定,每次有兩種不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在兩堆中同時取走相同數量的石子。最后把石子全部取完者為勝者。現在給出初始的兩堆石子的數目,如果輪到你先取,假設雙方都采取最好的策略,問最后你是勝者還是敗者。
輸入
輸入包含若干行,表示若干種石子的初始情況,其中每一行包含兩個非負整數a和b,表示兩堆石子的數目,a和b都不大于1,000,000,000。
輸出
輸出對應也有若干行,每行包含一個數字1或0,如果最后你是勝者,則為1,反之,則為0。
樣例輸入
2 1 8 4 4 7樣例輸出
0 1 0參考代碼
#include <iostream> #include <cmath> using namespace std; bool Wythoff(int n,int m){//判斷先手且為n,m時是否取勝 if(n>m) return Wythoff(m,n);//保證n<=m int k=m-n;//計算出項數k int _n=k*(sqrt(5)+1)/2.0;//計算出必敗時的n return n!=_n;//判斷是否必敗 } int main(){int n,m;while(cin>>n>>m){cout<<Wythoff(n,m)<<endl;}return 0; }總結
以上是生活随笔為你收集整理的【博弈论】威佐夫博弈的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 再谈6G
- 下一篇: 老机械设计工程师的工作心得