威佐夫博弈

来源:互联网 发布:海外淘软件知乎 编辑:程序博客网 时间:2024/06/05 21:02
有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。
Input
输入包含若干行,表示若干种石子的初始情况,其中每一行包含两个非负整数a和b,表示两堆石子的数目,a和b都不大于1,000,000,000。
Output
输出对应也有若干行,每行包含一个数字1或0,如果最后你是胜者,则为1,反之,则为0。
Sample Input
2 18 44 
Sample Output
010
#include<stdio.h>#include<math.h>double g=(sqrt(5.0)+1)/2;int main(){    int a,b,t;    while(scanf("%d %d",&a,&b)==2)    {        if(a>b)        {            t=a;            a=b;            b=t;        }        int k=b-a;        if(a==(int)(g*k))        {            printf("0\n");        }        else        {            printf("1\n");        }    }    return 0;}

分析
  1. (0,0) 先手必败,很明显他没得取了。
  2. (1,2) 先手必败。具体分析一下,先手有以下几种取法: 取第一堆的1个,后手取走第二堆的2个获胜。 从第一堆第二堆各取1个,后手取走第二堆剩下的1个获胜。 取第二堆的1个,后手从第一堆第二堆各取1个获胜。 取第二堆的2个,后手取走第一堆的1和获胜。 综上所述,先手必败。
  3. (3,5) 先手必败。 首先可以明确的一点是,先手不能把任意一堆取完,如果取完显然必败。 先讨论先手从第一堆中取的情况 先手可以从第一堆中取1个,后手从第二堆中取4个,转化为(1,2),先手必败。 先手可以从第一堆中取2个,后手从第二堆中取3个,转化为(1,2),先手必败。 再讨论先手从第二堆中取的情况 先手可以从第二堆中取1个,后手从两堆中各取2个,转化为(1,2),先手必败。 先手可以从第二堆中取2个,后手从两堆中各取3个,转化为(0,0),先手必败。 先手可以从第二堆中取3个,后手从两堆中各取1个,转化为(1,2),先手必败。 先手可以从第二堆中取4个,后手从第一堆中取2个,转化为(1,2),先手必败。 接着讨论先手从两堆中取的情况 先手可以从两堆中各取1个,转化为(2,4),此时情况较多 后手足够聪明,他从第二堆中取了1个,转化为(2,3),先手也足够聪明,他为了不直接输掉,从第一堆中取了1个(其他取法直接输掉了),转化为(1,3),此时后手从第二堆中取1个,转化为(1,2),先手必败。 先手可以从两堆中各取2个,后手从第二堆中取一个,转化为(1,2),先手必败。 综上所述,先手必败。
  4. 其他的先手必败局势 (4,7),(6,10),(8,13),(9,15),(11,18).

  5. 我们将先手必败局势的集合,称为奇异局势。

奇异局势的性质

  1. 任何自然数都包含在一个且仅有一个奇异局势中。
  2. 任意操作都可将奇异局势变为非奇异局势。
  3. 采用适当的方法,可以将非奇异局势变为奇异局势。

Betty定理

我们可以发现,将所有奇异局势按照第一堆的石子的数目从小到大排列,每个奇异局势的差值是自然数列。 进一步观察发现,对于一个奇异局势(A,B), A = 下取整[ (B-A) * 1.618 ],更准确的说,1.618 = (sqrt(5) + 1) / 2.

为什么会是这样的? 具体的证明涉及到Betty的定理,有兴趣的读者可以百度,这里不再赘述。

常见的几类问题

  1. 给出一个局面,判断先手输赢。 检查是否是奇异局势。
  2. 给出局面,判断先手输赢,若赢,求出首步取法。 由于差值是固定的,根据差值计算。
原创粉丝点击