1. 程式人生 > >博弈論-Nim博弈

博弈論-Nim博弈

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;
		}
	}
}