您的位置:首页 > 其它

POJ-1067 取石子游戏(威佐夫博弈)

2016-07-20 16:31 399 查看
题目链接

POJ-1067 取石子游戏

题目大意

有两堆石子,数量分别为\(a,b\),两个人轮流取石子。每次有两种不同的取法:一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最优策略,问最后你是胜者还是败者?

Sample Input

2 1

8 4

4 7

Sample Output

0

1

0

思路

直接是:威佐夫博弈。

这个过于繁琐,只能运用现成的结论。

设奇异局势(必败局势)为(a[i],b[i]),则有a[0]=b[0]=0;a[k]=前面未出现的最小自然数,b[k]=a[k]+k

具体求解公式:a[k]=k∗1+5√2,b[k]=a[k]+k=k∗3+5√2

奇异局势的性质:

1.任何自然数包含在且仅包含在一个奇异局势中

a[k]>a[k−1],b[k]=a[k]+k>a[k−1]+k−1=b[k−1]>a[k−1],则任意奇异局势中不存在相同的自然数(除了(0,0)),又a[k]前面未出现的最小自然数,则任何自然数均会出现在奇异局势中

2.任意操作均为将奇异局势变为非奇异局势

①在一堆中取石子,由于另一堆中的数不会出现在其他奇异局势中,则新局势必定非奇异局势

②在两堆中同时取石子,由于两堆石子差值不变,而序号为差值的奇异局势唯一,则新局势必定非奇异局势

3.任意非奇异局势可以通过特定操作转化为奇异局势

设当前局势为(a,b)。

①a==b时:同时从两堆取走a个石子,转化为(0,0)

②a==a[k]&&b>b[k]时:从第二堆取走b−b[k]个石子,转化为(a,b[k])

③a==a[k]&&b<b[k]时:同时从两堆取走a−a[b−a]个石子,转化为(a[b−a],b−a+b[b−a])

④a>a[k]&&b==b[k]时:从第一堆取走a−a[k]个石子,转化为(a[k],b)

⑤a<a[k]&&b==b[k]时:若a==a[j] (j<k),则从第二堆取走b−b[j]个石子,转化为(a,b[j]);否则必有a==b[j](j<k),则从第二堆取走b−a[j]个石子,转化为(a[j],a)

代码

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;

int a,b,aa;
double x;

int main() {
x=(1.0+sqrt(5.0))/2.0;
while(2==scanf("%d%d",&a,&b)) {
if(a>b) {
swap(a,b);
}
aa=floor((b-a)*x);//计算第b-a个奇异局势
printf("%d\n",a==aa?0:1);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息