很明显,编程并不是这一道题目的重点,重点是题目背后的知识——威佐夫博弈。其实这就是编程的魅力,有的时候代码本身并不难,难点还是在于代码背后的逻辑,还是在于人,只要你的大脑知道怎么做,那么代码肯定能写出来,所以说啊,写代码看似是在写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 人评分
C语言程序设计教程(第三版)课后习题6.3 (C++代码)浏览:755 |
C语言训练-阶乘和数* (C++代码)(直接输出样例hhhh)浏览:1177 |
C语言程序设计教程(第三版)课后习题12.6 (C语言代码)浏览:816 |
C语言训练-斐波纳契数列 (C语言代码)浏览:3015 |
C语言程序设计教程(第三版)课后习题1.5 (C语言代码)浏览:672 |
C语言训练-排序问题<1> (C语言代码)浏览:636 |
字符逆序 (C语言代码)浏览:506 |
C语言程序设计教程(第三版)课后习题5.7 (C语言代码)浏览:537 |
C语言程序设计教程(第三版)课后习题11.1 (C语言代码)浏览:525 |
Pascal三角 (C语言代码)浏览:707 |