POJ - 1740 A New Stone Game (博弈论)

题意:给你n堆石子,每次你可以选择在一堆中取至少一颗石子,之后可以选择(也可以不选择)将一堆剩下的石子放到其他堆里面,问最后水不能取谁输。

思路:首先明确一点,当只有两堆且两两相等的时候,先手取什么后手对称取他,这样的话后手肯定赢,4堆且两两相等的时候也一样,因为我们把两两相等的两堆看成两个游戏(A,B)先手会拿A的第一颗,那么后手会拿A的最后一颗,那么之后先手就肯定只能拿B的第一颗石子,后手必定拿B的最后一颗石子,先手输。。那么对于不一样的4堆怎么办?我们取4堆中的最大值,之后让他变成4堆中最小的一个,之后我们利用最小值和最大值的差值就补平那些不一样的就好了,这样就会得到4个完全相等的,把必败局面留给了后手,,那么对于奇数堆呢,先手可以把奇数堆全部拿完,之后分到不平等的偶数堆里面,使他变成相等的奇数堆,先手还是必胜的,那么由此可以知道什么时候先手必输,就是她直接面临的是偶数堆,且偶数堆的两两相等,这样后手就可以直接模仿先手的操作了,所以说如果是奇数堆先手必胜,如果是偶数堆,判断,如果偶数堆本来就是两两相等的,那么先手必输,如果不是那么先手必赢。

上代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int maxn = 100+10;
int a[maxn];
int main()
{
	int n;
	while(scanf("%d",&n)!=EOF)
	{
		if(n == 0) break;
		for(int i = 0 ; i < n ; i++)
		{
			scanf("%d",&a[i]);
		}
		if(n&1) puts("1");
		else 
		{
			sort(a,a+n);
			int flag = 0;
			for(int i = 0 ; i < n ;i +=2)
			{
				if(a[i] != a[i+1])
				{
					flag = 1;
					break;
				}
			}
			if(flag)
			{
				puts("1");
			}
			else 
			{
				puts("0");
			}
		}
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/wjmwsgj/article/details/80196015