https://leetcode-cn.com/problems/nim-game/
题目:你和你的朋友,两个人一起玩 Nim 游戏:
桌子上有一堆石头。
你们轮流进行自己的回合,你作为先手。
每一回合,轮到的人拿掉 1 - 3 块石头。
拿掉最后一块石头的人就是获胜者。
假设你们每一步都是最优解。请编写一个函数,来判断你是否可以在给定石头数量为 n 的情况下赢得游戏。如果可以赢,返回 true;否则,返回 false 。
示例 1:
输入:n = 4
输出:false
解释:如果堆中有 4 块石头,那么你永远不会赢得比赛;
因为无论你拿走 1 块、2 块 还是 3 块石头,最后一块石头总是会被你的朋友拿走。
示例 2:
输入:n = 1
输出:true
示例 3:
输入:n = 2
输出:true
归纳推理:
假设最后一块石头在第 i 局结束。又因为我们是先手,则只有在奇数局结束时,我们才有可能赢。
分析过程:
1局结束。则需要 1~3 颗石头
3局结束。则,倒数第一局至少需要一颗石头
倒数第二局可选1~3,则证明,倒数第二局至少需要4块石头。
第一局的石头数需要满足,减去1~3颗石头后还可以剩4块,则可选4+1、4+2、4+3.
即 5,6,7
5局结束。则,倒数第一局至少需要一颗石头
...
倒数第三局:5,6,7
倒数第4局,至少需要8颗石头。因为 他拿3,剩余5. 他拿2,剩余6,他哪1,剩余7
第一局(倒数第5局):(8+1)=9,(8+2)=10,(8+3)=11
7局结束。则 ....
倒数第一局:1,2,3
倒数第三局:5,6,7
倒数第五局:9,10,11
倒数第7局:?
观察规律可得,每隔一轮(奇数局),石头数量+4. 则可假设第7局需要石头为 13,14,15
注,每次我拿完之后,都要保证剩余的至少为4的倍数(最多拿3个),这样不管他拿几个,总会在下下局留下至少一个,让最后的石头被我拿走。
比如4块石头:
- 他拿1块,剩余3块我可以全部拿走。
- 他拿2块,剩余2块我可以全部拿走。
- 他拿3块,剩余1块我可以全部拿走
证明第7局获胜的三种情况:
石头数量 | 第一局(我) | 第二局(他) | 第三局(我) | 第四局(他) | 第五局(我) | 第六局(他) | 第七局(我) |
---|---|---|---|---|---|---|---|
13块石头 | |||||||
我拿1,剩12, (剩余4的倍数,所以这里我只能选1块) 第3、5、7局同理 | |||||||
他拿1,剩11 | 我拿3,剩8 | 他拿1,剩7 | 我拿3,剩4 | 他拿1,剩3 | 我全拿,完 | ||
他拿2,剩2 | 我拿2,完 | ||||||
他拿3,剩1 | 我拿1,完 | ||||||
他拿2,剩6 | 我拿2,剩4 | 他拿1,剩3 | 我全拿,完 | ||||
他拿2,剩2 | 我拿2,完 | ||||||
他拿3,剩1 | 我拿1,完 | ||||||
他拿3,剩5 | 我拿1,剩4 | 他拿1,剩3 | 我全拿,完 | ||||
他拿2,剩2 | 我拿2,完 | ||||||
他拿3,剩1 | 我拿1,完 | ||||||
他拿2,剩10 | 我拿2,剩8 | ||||||
… | |||||||
他拿3,剩9 | 我拿1,剩8 | ||||||
… |
如上表所示,只要我们每次选则后,让下一轮都是4的倍数,那么我们总能赢。
而此题解题的关键在与,有多少个石头的时候我们能赢。观察能赢的1,3,5,7局的初始石头数量如下:
- 1:1,2,3
- 3:5,6,7
- 5:9,10,11
- 7:13,14,15
可以发现,只要初始石头数量不为4的倍数,那么我们总有办法获胜。
class Solution {
public:
bool canWinNim(int n) {
return n % 4 != 0;
}
};