stone(某博弈论题)

题目描述
有三堆石子,它们的石子个数分别为 x,y,z。
A 和 B 正在博弈,由 A 先手,双方轮流操作。
每次操作是指,选择若干堆(1~3 堆)石子,从中各取出相同数量的石子(不能 1 个都不取)。不能操作的人失
败。
请判定是否先手必胜。

先考虑两堆,先手必败的情况

(1,2),(3,5),(4,7),(6,10),(8,13);

每对两堆石子的差不相同,且每个数只出现了一次。

对于每个x,有唯一个y和它对应,出现先手必败的情况

考虑三堆 (a,b,c)

我们可以类比出每对a,b对应这有且只有一个c和它组成先手必败的情况。

对于(a,b,k)是先手必败的情况,c 为大于k的某一个数。

那么(a+c-k,b+c-k)组成先手必败的情况的第三堆的石子数不可能为c.

因为如果(a+c-k,b+c-k,c)为成先手必败的情况,那么先手同时在第1堆和第二堆取走c-k时(a,b,c)则为先手必败的情况,那么(a,b,k)则不可能为先手必败的情况,矛盾了所以(a+c-k,b+c-k)组成先手必败的情况的第三堆的石子数不可能为c.

同理(a+c-k,b),(a,b+c-k)为成先手必败的情况的第三堆的石子数也不可能为c。

那么c与(a,b)构成先手必败的情况的条件是,a和b没有在第三堆为c时出现过,a-b没有在第三堆为c时出现过。

#include<bits/stdc++.h> 
using namespace std;
const int ha = 301;
int f[ha+5][ha+5], bu[ha+5][ha+5],vis[1000],cha[1000];
void yuchuli()
{
	for(int i = 0; i <= ha; i++)
	 for(int j = 0; j <= ha; j++)
	 f[i][j] = 1e9;
	 memset(bu,0,sizeof(bu));
	for(int cc = 0; cc <= ha; cc++)
	{
			int c = cc + 1;
		for(int a = 0; a <= ha; a++)
	   for(int b = 0; b <= a; b++)
	  {
		if(f[a][b] < cc) 
		{
			int k = f[a][b];
			int v = cc - k;
			if((a + v) <= ha) bu[a + v][b] = c;
			if((b + v) <= ha) bu[a][b+ v] = c;
		    if(max(b+ v,a+ v) <= ha)bu[a+ v][b+v] = c;
		}
		else if(max(bu[a][b],bu[b][a]) < c && (vis[a] < c) && (vis[b] < c) && (cha[abs(a - b)] < c))
	      {
	      	if(cc == 301) 
	      	int haha = 1;
	      	f[a][b] = f[b][a] = cc;
	      	vis[a] = c;
	      	vis[b] = c;
	      	cha[abs(a - b)] = c;
	      }
	  }
	}

}
int main()
{
	yuchuli();
	int t;
	cin >> t;
	for(int i = 1;  i <= t; i++)
	{
		int x,y,c;
		scanf("%d%d%d",&x,&y,&c);
		if(f[x][y] == c) cout << "No" << endl;
		else cout << "Yes" << endl;
	}
	return 0;
}

.

猜你喜欢

转载自blog.csdn.net/Bluelanzhan/article/details/83115928