博弈論 演算法

2021-10-14 17:08:58 字數 4123 閱讀 4221

博弈論主要研究公式化了的激勵結構間的相互作用,是研究具有鬥爭或競爭性質現象的數學理論和方法。博弈論考慮遊戲中的個體的**行為和實際行為,並研究它們的優化策略。如囚徒困境(鏈結)。

在演算法競賽**現的博弈論題目通常是icg(公平組合遊戲)的,有如下特徵:

1.有兩名選手。

2.兩名選手交替操作,每次一步,每步都是在有限的合法集合中選取一種進行。

3.在任何情況下,合法操作只取決於情況本身,與選手無關。

4.遊戲的敗北條件為:當某位選手需要進行操作時,當前沒有任何可以執行的合法操作,則該選手敗北。

尋找必敗態即為針對此類試題給出一種解題思路。

一堆n個物品,兩個人輪流從中取出(1~m)個,最後取光者勝,如何判斷先手贏還是後手贏。

顯然,如果n=m+1,那麼由於一次最多只能取m個,所以無論先取者拿走多少個,後取者都能夠一次拿走剩餘的物品,後取者勝。所以當一方面對的局勢是n%(m+1)=0時,其面臨的是必敗的局勢 。由此我們可以得到取勝的法則:如果n=(m+1)*r+s,(r 為任意自然數,s≤m),那麼先取者要拿走s 個物品,如果後取者拿走k(k≤m)個,那麼先取者再拿走m+1-k個,結果剩下(m+1)*(r-1)個,以後保持這樣的取法,那麼先取者肯定獲勝。總之,要保證給對手留下(m+1)的倍數,就能最後獲勝。

例題1:

一天,tt在寢室閒著無聊,和同寢的人玩起了取石子遊戲,而由於條件有限,他們是用旺仔小饅頭當作石子。遊戲的規則是這樣的。設有一堆石子,數量為n(1<=n<=1000000),兩個人輪番取出其中的若干個,每次最多取m個(1<=m<=1000000),最先把石子取完者勝利。我們知道,tt和他的室友都十分的聰明,那麼如果是tt先取,他會取得遊戲的勝利麼?

輸入

第一行是乙個正整數n表示有n組測試資料

輸入有不到1000組資料,每組資料一行,有兩個數n和m,之間用空格分隔。

輸出

對於每組資料,輸出一行。如果先取的tt可以贏得遊戲,則輸出「win」,否則輸出「lose」(引號不用輸出)

題解:

#include

#include

intmain()

system

("pause");

return0;

}

例題2:

lele聽說街上正在舉行一場別開生面的拍賣會,拍賣的物品正好就是一塊20畝的田地。於是,lele帶上他的全部積蓄,衝往拍賣會。後來發現,整個拍賣會只有lele和他的死對頭yueyue。通過打聽,lele知道這場拍賣的規則是這樣的:剛開始底價為0,兩個人輪流開始加價,不過每次加價的幅度要在1~n之間,當**大於或等於田地的成本價 m 時,主辦方就把這塊田地賣給這次叫價的人。lele和yueyue雖然考試不行,但是對拍賣卻十分精通,而且他們兩個人都十分想得到這塊田地。所以他們每次都是選對自己最有利的方式進行加價。由於lele字典序比yueyue靠前,所以每次都是由lele先開始加價,請問,第一次加價的時候,lele要出多少才能保證自己買得到這塊地呢?

輸入:

本題目包含多組測試,請處理到檔案結束(eof)。每組測試佔一行。每組測試包含兩個整數m和n(含義見題目描述,0輸出:

對於每組資料,在一行裡按遞增的順序輸出lele第一次可以加的價。兩個資料之間用空格隔開。如果lele在第一次無論如何出價都無法買到這塊土地,就輸出"none"。

sample input

4 23 2

3 5sample output

1none

3 4 5

題解:

只要加價讓剩餘**是(n+1)的倍數,就可以到達必敗點。

如果m是(n+1)的倍數,lele輸

如果m大於等於n,lele贏

如果m不是(n+1)的倍數,那麼加價m%(1+n)),lele就可以贏

#include

#include

intmain()

else

printf

("\n");

}else}}

system

("pause");

return0;

}

巴什博弈有一種變形,叫做減法博弈。用s表示乙個正整數構成的集合,基於s所定義的減法遊戲可以描述如下:

有乙個由n個石子組成的石子堆,兩名玩家輪流從中拿走石子,每次拿走石子的個數只能是集合s中的數。拿走最後一枚石子的玩家獲勝。

例:s = ,如果在遊戲的開始有100枚石子,判斷先手的輸贏

題解:

可以通過由小到大找規律,找出n和p來確定100是必敗態還是必勝態。

x0123456789101112狀態p

npnn

nnpn

pnnn

通過觀察發現,該遊戲中的p位置(必敗態)是那些能被7整除或者模7餘2的位置,其他位置都是n位置(必勝態)。

//減法博弈

intmain()

system

("pause");

return0;

}

有兩堆各若干個物品,兩個人輪流從某一堆或同時從兩堆中取同樣多的物品,規定每次至少取乙個,多者不限,最後取光者得勝。

解決思路:a:設(ai,bi)(ai ≤bi ,i=0,1,2,…,n)表示兩堆物品的數量並稱其為局勢,如果甲面對(0,0),那麼甲已經輸了,這種局勢我們稱為奇異局勢。

分析:

那麼任給乙個局勢(a,b),怎樣判斷它是不是奇異局勢呢?

我們總結了如下公式:ak =[k(1+√5)/2],bk= ak + k (k=0,1,2,…,n 方括號表示取整函式)

威佐夫博弈常見的問題:

給你乙個局面,讓你求先手的輸贏。

有了上面的分析,那麼這個問題應該不難解決。首先求出差值,差值 * 1.618 == 最小值 的話後手贏,否則先手贏。(注意這裡的1.618最好是用上面式子計算出來的,否則精度要求高的題目會錯)

給你乙個局面,讓你求先手的輸贏,假設先手贏的話輸出他第一次的取法。

首先討論在兩邊同時取的情況,很明顯兩邊同時取的話,不論怎樣取他的差值是不會變的,那麼我們可以根據差值計算出其中的小的值,然後加上差值就是大的乙個值,當然能取的條件是求出的最小的值不能大於其中小的一堆的石子數目。

假如在一堆中取的話,可以取任意一堆,那麼其差值也是不定的,但是我們可以列舉差值,差值範圍是0 — 大的石子數目,然後根據上面的理論判斷滿足條件的話就是一種合理的取法。

例題:

有兩堆石子,數量任意,可以不同。遊戲開始由兩個人輪流取石子。遊戲規定,每次有兩種不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在兩堆中同時取走相同數量的石子。最後把石子全部取完者為勝者。現在給出初始的兩堆石子的數目,如果輪到你先取,假設雙方都採取最好的策略,問最後你是勝者還是敗者。

sample input

2 18 4

4 7sample output:(如果最後你是勝者,則為1,反之,則為0)

題解

注意要保證前乙個數字比第二個數字小

#include

#include

intmain()

q =(1

+sqrt(5

))/2

;if(int

((b-a)

*q)== a)

printf

("0\n");

else

printf

("1\n");

}return0;

}

博弈論演算法

複習 兩個頂尖聰明的人在玩遊戲,有一堆n個石子,每次每個人能取 1,m 個石子,不能拿的人輸,請問先手與後手誰必敗?結論 通過上面的分析可以得出結論 當n能整除m 1時先手必敗,否則先手必勝。兩個頂尖聰明的人在玩遊戲,有nn堆石子,第ii堆有aiai個,每人每次能從一堆石子中取任意多個石子但不能不取...

演算法 簡單博弈論

僅有一堆n個物品,兩個人輪流取1 m個,最後取的人勝 不能取的人輸 總體可分幾種情況 int bash game int n,int m 是否先手有必贏策略 將一堆變為多堆 即 有3堆各若干個物品,兩個人輪流從某一堆取任意多的物品,規定每次至少取1個,多者不限,最後取光者得勝。本部分含其他部落格內容...

博弈論 Nim博弈

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