【算法与数据结构】—— 博弈论(高阶篇之反尼姆博弈)

博弈论之反尼姆博弈

反尼姆博弈:
有任意堆物品,每堆物品的个数是任意的,双方轮流从中取物品,每一次只能从一堆物品中取部分或全部物品,最少取一件,取到最后一件物品的人失败。

下面直接给出反尼姆博弈中判断必胜局的条件,满足其中任意一点都能取胜:
1.各堆物品数目异或结果不等于0,且存在有石子数目大于1的物品堆
2.各堆物品数目异或结果等于0,且所有物品堆数目全部为1



---经典题型---



问题引入
最近Sam和Ted在玩一个游戏,游戏是这样的。
有n堆石子,两个人轮流从其中某一堆中任意取走一定的石子,最后不能取的为赢家。注意:每次只能从一堆取任意个,可以取完这堆,但不能不取。
假设Sam先取,输出胜者的名字。

数据输入
第一行输入n,代表有n组测试数据(n<=10000)。
以下每组测试数据包含两行:
第一行:包含一个整数m,代表本组测试数据有m(m<=1000)堆石子;
第二行:包含m个整数Ai(Ai<=10000),分别代表第i堆石子的数量。

数据输出
对于每组测试数据,若Sam胜利则输出“Sam”,否则输出“Ted”。

样例输入
3
2
1 1
3
3 8 11
2
5 10

样例输出
Sam
Ted
Sam


分析:
本题是反妮姆博弈的典型例题,趁热打铁,我们直接利用前面的结论即可解答本题
下面直接给出本题的完整代码:

#include<iostream>
using namespace std;
int main()
{
	int n,m,var,temp;
	bool flag;
	cin>>n;
	while(n--)
	{
		cin>>m;
		var=0,flag=false;
		for(int i=0;i<m;i++){
			cin>>temp;
			var^=temp;
			if(temp>1) flag=true; 
		}
		if((var && flag)||(!var && !flag)) cout<<"Sam"<<endl;
		else cout<<"Ted"<<endl;
	}
	return 0;
}
发布了38 篇原创文章 · 获赞 75 · 访问量 9519

猜你喜欢

转载自blog.csdn.net/the_ZED/article/details/104372804