同样威佐夫也有一个经典的例题:
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 --- 大的石子数目,然后根据上面的理论判断满足条件的话就是一种合理的取法。