取(2堆)石子游戏 HDU - 2177

原题链接
考察:博弈论
思路:
  威佐夫博弈,求先手必胜的第一步.
  要先手必胜,即把后手面临的局面改为先手必败.当n==(m-n)*k即先手必败.这里分两种情况:

  1. (m-n)*kd,d<n时,我们可以从n堆里取,但我们需要保证新局面下m,与n的差值不变,才能保证差值*kn
  2. 从m堆里取,此时m堆的值不可预知,只能枚举判断是否为先手必败.

Code

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const double eps = (sqrt(5)+1)/2;
int n,m;
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF&&(n+m))
	{
		if(n>m) swap(n,m);
		int d = m-n;
		int x = d*eps; 
		if(x==n) {puts("0"); continue;} 
		puts("1");
		if(x<n) printf("%d %d\n",x,m-n+x);//两堆同时 
		int t = n;
		for(int i=1;i<=m;i++)//从m堆里取 
		{
			int s = m-i;
			if(s<t) swap(s,t);//t更小
			d = s-t;
			x = d*eps;
			if(x==t) printf("%d %d\n",min(t,s),max(s,t)); 
			t = n;
		}
	}
	return 0;
}

上一篇:【数据结构】HashMap 面试题8问


下一篇:集合常用方法