题目:你和你的朋友,两个人一起玩 Nim 游戏:
桌子上有一堆石头。 你们轮流进行自己的回合, 你作为先手 。 每一回合,轮到的人拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。 假设你们每一步都是最优解。请编写一个函数,来判断你是否可以在给定石头数量为 n 的情况下赢得游戏。如果可以赢,返回 true;否则,返回 false 。
思路:看到这个题目,我就想起来一个走楼梯的题,走一步或者两步到达楼梯顶端,计算共有几种走法,emmm好像也不一样😛
采用倒推法模拟了一下,每个人都可以走1-3步,所以只要最后的石头堆里有1-3颗石头就一定会赢,当敌手是4颗石头时,无论是拿1颗,2颗还是3颗都是必输的局,当敌手是五颗石头时,可以选择(1,1,3),当敌手是六颗石头时,可以选择(2,1,3),当敌手是七颗时,可以选择(3,1,3),即五颗拿走1颗,六颗拿走2颗,七颗拿走3颗,让敌方陷入四颗石头的局面,则都是必胜状态。
当有八颗石头时,则是两个4颗石头的状态,无论如何都是必输的状态,其他以此类推。
注意以上都是最优解的条件下。以下是我的模拟过程。
通过以上模拟,所以得出了一个规律,就是当石头是4的倍数的时候,在最优解的条件下,是必输的状态,其他情况都一定会赢,代码如下:
bool canWinNim(int n) {
if(n % 4 == 0) return false;
return true;
}
这真是我写过的代码最少的算法题了,执行的时间更是不用说,提交结果如下:
总结:写题的时候多模拟,找出其中规律,便可以破题啦。
其实这是一个简单的博弈论,每次留下4的倍数给对手,就一定会赢,快去和小伙伴们玩Nim游戏吧,假装云淡风轻的赢下所有局,然后漫不经心收获小伙伴们的膝盖😁