威佐夫博弈

同样威佐夫也有一个经典的例题:

1.有两堆数量分别为 n,m个石子的石子堆;

2.两个人轮流取石子,可以在一堆石子中取任意个,或者,在两堆石子中每堆石子取相同数目的石子;

输出:

如果先手赢,输出1,否则输出0。

题解:

首先,当n=0,m=0时,先手输。

n=1,m=1时,先手赢。

n=2,m=1时,先手输。

......

......

n=3,m=5时,先手输。

n=4,m=7时,先手输。

n=6,m=10时,先手输。

......

根据规律,发现他们的差值是递增的,为 0,1,2,3,4,5,6......n,

再找规律,你会发现:

第一个值=差值*1.618;

1.618=(sqrt(5)+1)/2;

1 int n,m,a,b;
2 
3 a=max(n,m);
4 b=min(n,m);
5 
6 if(a-b==(sqrt(5)+1)/2)
7     printf("0
");
8 else
9     printf("1
"); 

下面来看看威佐夫博弈常见的其他问题:

1)给你一个局面,让你求是先手输赢。

有了上面的分析,那么这个问题应该不难解决。首先求出差值,差值 * 1.618 == 最小值 的话后手赢,否则先手赢。(注意这里的1.618最好是用上面式子计算出来的,否则精

度要求高的题目会错)

2)给你一个局面,让你求先手输赢,假设先手赢的话输出他第一次的取法。

       首先讨论在两边同时取的情况,很明显两边同时取的话,不论怎样取他的差值是不会变的,那么我们可以根据差值计算出其中的小的值,然后加上差值就是大的一个值,当

然能取的条件是求出的最小的值不能大于其中小的一堆的石子数目。

      加入在一堆中取的话,可以取任意一堆,那么其差值也是不定的,但是我们可以枚举差值,差值范围是0 --- 大的石子数目,然后根据上面的理论判断满足条件的话就是一种合理的取法。

原文地址:https://www.cnblogs.com/ouyang_wsgwz/p/6791836.html