威佐夫博弈: 有两堆各若干个物品,两个人轮流从任意一堆中取出至少一个或者同时从两堆中取出同样多的物品,规定每次至少取一个,至多不限,最后取光者胜利。
现在,我们有两个人Tony和Gogo,Tony先手,先输入一个数n,表示测试样例的个数,每次测试输入两个数a,b,那么我们的游戏谁会赢?
#include <stdio.h>
int main(){
int n;
scanf("%d",&n);
int i;
for(i=0;i<n;i++){
int a,b,max,min;
scanf("%d %d",&a,&b);
if(a<b){
max = b;
min = a;
}else{
max = a;
min = b;
}
double r = (sqrt(5.0) + 1) / 2;
double c;
c = (double)(max - min);
int temp = (int)(r*c);
if(temp == min){
printf("Gogo Wins!\n");
}else{
printf("Tony Wins!\n");
}
}
return 0;
}
我们在网上查找资料可以了解到,在这个游戏中,有一种”奇异局势“:当a和b中较小的那个数等于两个数的差值乘以1.618时(众所周知,0.618是黄金分割比,就是很奇妙啊是吧),就会出现先手必输的局面。
1.618 = (sqrt(5.0) + 1) / 2
但由于有些式子精度较高,我们就要用 (sqrt(5.0) + 1) / 2 否则可能会出现错误的输出。