很明显,编程并不是这一道题目的重点,重点是题目背后的知识——威佐夫博弈。其实这就是编程的魅力,有的时候代码本身并不难,难点还是在于代码背后的逻辑,还是在于人,只要你的大脑知道怎么做,那么代码肯定能写出来,所以说啊,写代码看似是在写ABCD,其实是在写你大脑中的逻辑!

    什么是威佐夫博弈呢,其实这道题目本身就已经是很好的描述了,我们简单来分析一下:

    第一个(0,0),肯定是先手输,为啥?因为当先手兴冲冲地上来准备拿第一手时,发现已经是(0,0)了,他没石子可拿了,那最后的石子去哪了?肯定在上一局被它对手取光了,所以先手只能认输,而对手稳赢,因为规则就是第一个把石头取光的赢得胜利。

    第二个(1,2),也是先手必输,为啥?因为先手上来取第一手时他只有四种取法:

        1):在1中取1个,那么后手就把2中剩余的2个全部取光:先手输,后手赢

        2):在2中取1个,那么后手在两堆中各取1个,石头又光了,先手又输了

        3):在2中取两个,后手取1中剩下的一个,石头又光了,先手又输了

        4):两堆中各取1个,后手取走2中剩余的1个,石头又光了,先手又输了

    综上所述,对于(1,2)这种情况,无论先手怎么取,都是死路一条,必输!

    第三个(3,5),先手还是死路一条,无论先手怎么取,最后兜兜转转都回到情形(1,2),上面已经分析过了,(1,2)先手必死无疑,可怜的先手啊!

    第四个 ( 6 ,10  )

    第五个 ( 8 ,13)

    第六个 ( 9 , 15)

    第七个 ( 11 ,18)……这些情况先手毫无招架能力,只能认输,那么这些数字到底有什么规律?规律有两个:
    一是从(0,0)开始到(11,18),两个数之间的差值是递增的分别是0,1,2,3,4,5,6,7……

    二是每一局中的第一个值是前面所有的局中没有出现的数字,比如第三个局面,前面出现了 0  1 2,那么第三个局面的第一个值为 3 ,比如第五个局面,前

面出现了 0  1  2 3 4 5 ,那么第五个局面第一个值为6。

    还有一个规律就是:第一个值 = 差值*1.618,这个才是解决此题的关键,而1.618 = (sqrt(5)+ 1) /  2 ,所以当我们拿着任意一组的两个值,只要判断一下是否符合“ 第一个值 = 差值*1.618”即可,如果是,那就是先手必输,不是,先手必赢!好了,看代码:

#include#include#include int main() {
    int a = 0, b = 0;
    while (~scanf("%d %d", &a, &b)) {
        //先把二者之中的较小值放在左侧
        if (a > b) {
            int temp = a;
            a = b;
            b = temp;
        }
        if (a == b) {//包括0 0这种特殊情况
            printf("1\n");//先手必胜
        } else if (a == (int)((b-a)*((sqrt(5)+1)/2))){
            printf("0\n");//先手必输
        } else {
            printf("1\n");//先手必赢
        }
    }
    return 0;
}


 

0.0分

10 人评分

  评论区

。。
2021-03-11 10:11:05
2021-03-11 10:10:55
超管有吗
2021-03-11 10:10:39
2021-03-11 10:10:18
删又删不掉,tmd烦死了
2021-03-11 10:09:52
完了,社死
2021-03-11 10:07:06
我去,这评论删不了吗
2021-03-11 10:06:21
说错了。。怎么删评论
2021-03-11 10:04:08