博弈论之反尼姆博弈
反尼姆博弈:
有任意堆物品,每堆物品的个数是任意的,双方轮流从中取物品,每一次只能从一堆物品中取部分或全部物品,最少取一件,取到最后一件物品的人失败。
下面直接给出反尼姆博弈中判断必胜局的条件,满足其中任意一点都能取胜:
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;
}