NYOJ博弈系列-取石子

如果不了解博弈,请先去看看基本的博弈知识。

http://blog.csdn.net/niushuai666/article/details/6638943

NYOJ上博弈类题目链接:

http://acm.nyist.net/JudgeOnline/keysearch.php?key=%E5%8F%96%E7%9F%B3%E5%AD%90

第一个:巴什博弈

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=23

题意:设有一堆石子,数量为N(1<=N<=1000000),两个人轮番取出其中的若干个,每次最多取M个(1<=M<=1000000),最先把石子取完者胜利。

解题思路:

模板题。

#include<iostream>
using namespace std;
int main()
{
	int k;
	long m,n;
	cin>>k;
	while(k--)
	{
		cin>>n>>m;
		if(n%(m+1)==0)
			cout<<"Lose"<<endl;
		else
			cout<<"Win"<<endl;
	}
}   

第二个: 威佐夫博弈


题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=161

题意:有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者

解题思路:

模板题。

 
#include <iostream>
#include <cmath>
 
using namespace std;
 
int main()
{
	 
	int m,n;	
	while(cin>>m>>n)
	{
		if (m > n)
		{
			int temp;
			temp = m;
			m = n;
			n =temp;
		}
		int k = n - m;
		int data = floor(k*(1.0+sqrt(5.0))/2.0);
		if (data == m)
			cout<<0<<endl;
		else
			cout<<1<<endl;
	}
}        
第三个: 尼姆博弈+巴什博弈


题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=135

解题思路:

这道题是巴什博弈和尼姆博弈的杂糅,因为尼姆博弈要求对每一堆石子可以取1-全部,而这道题限制了个数,就成为了巴什博弈。那为什么可以用尼姆博弈的思想来求解呢?

因为我们可以发现,当我们使用巴什博弈取到最后一次时,得到的n%(m+1)结果肯定<m,这样就符合了尼姆博弈的要求,进而可以用尼姆博弈的异或运算来求解。


#include<cstdio>
int main(){
	int T; 
	scanf("%d",&T);
	while(T--){
		int m,n,g,sum=0;
		scanf("%d",&g);
		while(g--){scanf("%d%d",&m,&n);sum ^= m % (n + 1);}
		puts(sum?"Win":"Lose");
	}
}        




你可能感兴趣的:(C语言,博弈,nyoj)