博弈论-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;
		}
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_41863129/article/details/85409040