博弈論-Nim博弈
阿新 • • 發佈:2019-01-02
1.Nim博弈的起源很早,至於歷史我們就不再說了,直接說它的使用場景。(1)依舊是兩個人博弈,但是物品時n堆,每一堆有ai個。(2)每個人可以挑選一堆取走若干個,但是不能不取。(3)最先取完所有物品的人獲勝。(4)結論:所以堆的物品的數量異或起來是0,先手必敗。
2.一個Nim博弈的例項:Nim博弈。乍一看這題和Nim博弈有啥關係?其實仔細分析之後它就是個Nim博弈。首先n行,其實就是有n堆的物品,每一行a,b之間的間隔,其實就是這堆物品的數量,為什麼這樣說,因為a和b都可以走格子,就相當於都可以拿走物品,但是這裡有一個問題,a,b的方向不一定就是相對的啊,他倆可以向同一個方向跑啊。那麼如果我們繼續使用剛才的觀點解釋,那麼這裡不就是在增加二者之間的距離,也就是在該堆物品中加入新的物品,那麼對於先手來說,它就有可能改變自己的必敗態(假設先手現在是必敗態),那麼這不是Nim博弈啊。顯然,我們在思考這個問題的時候,把博弈的另一方當成了傻子,事實上,他是很聰明的。假設先手現在時必敗態,那麼對應他自己就是必勝態,先手如果通過剛才我們描述的方式來增大二者之間的距離,改變自己的必敗態,這個時候後手其實很輕鬆就瓦解掉這個小把戲,行把,你不是加嗎?那我就減唄,他可以朝著相同的方向移動相同的步數,這樣就維持了自己的必勝態。所以,這個題還是NIm博弈。
3.分析好了之後,程式碼寫起來就很簡單了。
#include<iostream> #pragma warning(disable:4996) /* nim博弈: (1)二人博弈 (2)n堆物品 (3)任何一方可以選擇一堆物品並且拿走若干個,但是不能不拿 (4)先拿完所有物品的選手獲勝 */ using namespace std; int main() { int n, m; while (~scanf("%d%d", &n, &m)) { int a, b; int ans = 0; for (int i = 0; i < n; i++) { scanf("%d%d", &a, &b); ans = ans ^ (abs(b - a) - 1); } if (ans) { cout << "I WIN!" << endl; } else { cout << "BAD LUCK!" << endl; } } }