理論分析
問題:首先有兩堆石子,博弈雙方每次可以取一堆石子中的任意個,不能不取,或者取兩堆石子中的相同個。先取完者贏。
分析:首先我們根據條件來分析博弈中的奇異局勢
第乙個(0 , 0),先手輸,當遊戲某一方面對( 0 , 0)時,他沒有辦法取了,那麼肯定是先手在上一局取完了,那麼輸。
第二個(1, 2 ),先手輸,先手只有四種取法,
1)取 1 中的乙個,那麼後手取第二堆中兩個。
2)取 2 中乙個,那麼後手在兩堆中各取乙個。
3)在 2 中取兩個,那麼後手在第一堆中取乙個。
4)兩堆中各取乙個,那麼後手在第二堆中取乙個。
可以看出,不論先手怎麼取,後說總是能贏。所以先手必輸!
第三個 ( 3 , 5 ),先手必輸。首先先手必定不能把任意一堆取完,如果取完了很明顯後手取完另一堆先手必輸,那麼
假如看取一堆的情況,假設先手先在第一堆中取。 取 1 個,後手第二堆中取4個,變成(1 ,2)了,上面分析了是先手的必輸局。
取 2 個,後手第二堆中取3個,也變成( 1 , 2)局面了。
假設先手在第二堆中取,取 1 個,那麼後手在兩堆中各取 2 個,也變成 ( 1 , 2 )局面了。
取 2 個 ,那麼後手可以兩堆中都去三個, 變成 ( 0 , 0)局面,上面分析其必輸。
取 3 個,後手兩堆各取 1 個 ,變成( 1 , 2)局面了。
取 4 個,後手在第一堆中取乙個,變成( 1 , 2)局面了。
可見不論先手怎麼取,其必輸!
第四個(4 , 7),先手必輸。
自己推理可以發現不論第一次先手如何取,那麼後手總是會變成前面分析過的先手的必輸局面。
那麼到底有什麼規律沒有呢,我們繼續往下寫。
第5個 ( 6 ,10 )
第6個 ( 8 ,13)
第7個 ( 9 , 15)
第8個 ( 11 ,18)
會發現他們的差值是遞增的,為 0 , 1 , 2, 3, 4 , 5 , 6, 7.....n
而用數學方法分析發現局面中第乙個值為前面局面中沒有出現過的第乙個值,比如第三個局面,前面出現了 0 1 2,那麼第三個局面的第乙個值為 3 ,比如第五個局面,前
面出現了 0 1 2 3 4 5 ,那麼第五個局面第乙個值為6。
再找規律的話我們會發現,第乙個值 = 差值 * 1.618
而1.618 = (sqrt(5)+ 1) / 2。
大家都知道0.618是**分割率。而威佐夫博弈正好是1.618,這就是博弈的奇妙之處!
下面來看看威佐夫博弈常見的兩類問題:
1)給你乙個局面,讓你求是先手輸贏。
有了上面的分析,那麼這個問題應該不難解決。首先求出差值,差值 * 1.618 == 最小值 的話後手贏,否則先手贏。(注意這裡的1.618最好是用上面式子計算出來的,否則精
度要求高的題目會錯)
2)給你乙個局面,讓你求先手輸贏,假設先手贏的話輸出他第一次的取法。
首先討論在兩邊同時取的情況,很明顯兩邊同時取的話,不論怎樣取他的差值是不會變的,那麼我們可以根據差值計算出其中的小的值,然後加上差值就是大的乙個值,當
然能取的條件是求出的最小的值不能大於其中小的一堆的石子數目。
加入在一堆中取的話,可以取任意一堆,那麼其差值也是不定的,但是我們可以列舉差值,差值範圍是0 --- 大的石子數目,然後根據上面的理論判斷滿足條件的話就是一種合理的取法。
1.hdoj 取石子遊戲
**:
#include #includeview code#include
#include
#include
#include
#include
#include
#include
#include
#define i scanf
#define ol puts
#define o printf
#define f(a,b,c) for(a=b;a#define ff(a,b) for(a=0;a#define fg(a,b) for(a=b-1;a>=0;a--)
#define len 1000
#define max 1<<30
#define v vectorusing
namespace
std;
intmain()
return0;
}
直接用公式if(a==delta*(1.618))得到
2.nyoj wythoff game
**:
#include #includeview code#include
#include
#include
#include
#include
#include
#include
#include
#define i scanf
#define ol puts
#define o printf
#define f(a,b,c) for(a=b;a#define ff(a,b) for(a=0;a#define fg(a,b) for(a=b-1;a>=0;a--)
#define len 100005
#define max 1<<30
#define v vectorusing
namespace
std;
inta[len];
intb[len];
intv[len];
int cnt=0
;void build(int
n) }
}}int
main()
puts(
"");}}
這段**體現了威佐夫博弈必敗點生成的過程,非常有學習意義:
博弈論 威佐夫博弈
1.威佐夫博弈的條件 1 人數為兩人 2 物品為兩堆,每乙個人在取物品的時候要麼在一堆中取若干物品,要麼在兩堆中取相等的物品。每次至少乙個,可以取完這一堆。3 先手必敗的條件 在奇異局勢下必敗。2.ok,如果你不是很懂什麼叫做奇異局勢,那麼聽我解釋。我們知道物品兩為兩堆,每一堆的數量數a,b。我們記...
博弈論入門之威佐夫博弈
威佐夫博弈是一類經典的博弈問題 有兩堆石子,兩個頂尖聰明的人在玩遊戲,每次每個人可以從任意一堆石子中取任意多的石子或者從兩堆石子中取同樣多的石子,不能取得人輸,分析誰會獲得勝利 威佐夫博弈不同於nim遊戲與巴什博奕,它的特殊之處在於不能將兩堆石子分開分析。前輩們在對該博弈遊戲做了大量的探索之後最終找...
博弈論 威佐夫博弈原理與證明
威佐夫博弈的定義是 有兩堆若干個物品,兩人輪流從某一堆物品中取至少乙個或同時從兩堆中取相同數量的物品,不能不取,最後把物品全部取完者勝利 現在給出兩堆物品的數量 n,m 判斷先手是否有策略必勝 我們用 a,b 表示第一堆數量為 a 第二堆數量為 b 的局勢,並規定 a leq b 因為所有局勢經過互...