https://leetcode-cn.com/problems/nim-game/description/
你和你的朋友,两个人一起玩 Nim游戏:桌子上有一堆石头,每次你们轮流拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。你作为先手。
你们是聪明人,每一步都是最优解。 编写一个函数,来判断你是否可以在给定石头数量的情况下赢得游戏。
示例:
输入: 4
输出: false
解释: 如果堆中有 4 块石头,那么你永远不会赢得比赛;
因为无论你拿走 1 块、2 块 还是 3 块石头,最后一块石头总是会被你的朋友拿走。
这个题初看之下摸不着头脑,但我们一步一步想这个问题就会迎刃而解。
依题意,当做出选择时手头有特定数量的石头时,足够聪明的人是永远能够获胜的。因为我和对手都极其聪明(帅),而我们作为先手要做的就是留给对方一个无法获胜的局面,我们先从石子数量小时开始思考。
当石子数为1~3时,我们作为先手无论如何都能取胜,我们称手头有1~3颗石子时为胜利区。而数量为4时,我们拿走石子后剩余石子的数量为1~3·也就是把胜利区留给了对手,也就是无论如何我们都会输掉,我们称手头有4颗石子时为死亡点。那么如果我们能先手取走一定数量石子后把死亡点留给对手的话,我们就一定能胜利,那么4+(1~3)也就是5~8时,我们可以取走1~3颗石子将死亡点留给对手,所以5~8也是胜利区。将死亡点留给对手能获得胜利,换言之如果将胜利区给对手,因为他像卖金克拉的美国佬一样狡猾,那么他也一定能利用胜利区获胜。所以当我们面前有8颗石子时就会像4颗一样,无论取多少颗都会留给对手胜利区,所以8又成为了死亡点。分析到这里,相信聪明的社会主义接班人已经发现了这是一个循环,因为我们只能拿走1~3颗石子,所以死亡区以4为周期出现,所以我们当然是每逢四的倍数必输喽:)
我们还有另外一种更为简洁的思路,因为当自己取石子时数量为4会输。由于我们是先手,并且可以取走1~3颗石子,所以我们可以保证我们不是4的倍数时,可以永远让对手拿到4的倍数,而石子数目一直减少,对手永远拿到4的倍数,最终一定会拿到4,他就一定会输掉。
代码十分简单,如下
class Solution {
public:
bool canWinNim(int n) {
if(n%4==0){
return 0;
}
else
return 1;
}
};