这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战
题目
PS:在不知道学什么的时候,只能刷刷题了,Spring和JVM看着着实累人
解析
博弈论的问题一概都很恶心,之前也有过类似的题解(比如说之前的各种石子游戏)。不过既然刷到了,就看看怎么做吧,万一面试问到了呢。
分析一下:拿到最后一个石子的,赢了。
那么这就代表着:
- 如果在最后一次我取的时候,只能取到这堆东西剩1~3个,那么我是必输的。
- 反过来,如果最后一次对手取的时候,只能取到这堆东西剩1~3个,那么我必赢。
这个条件就代表着:如果A必赢,那么A倒数第二次取之后,就会恰好剩4个,这样无论对手最后一次怎么取,自己都可以取到最后一个;这个恰好剩4个,就可以转化为取得倒数第5个的人必然会获胜。
那么就得到了第一个看起来像样的推导答案:
取得最后一个的人会获胜->取得倒数第五个的人会获胜。
同理可以推得:取得倒数第9个的人必定获胜。
因此得出一个公式:
取得倒数第4i+1个石子的人,必然获胜,i>=1。
另外:在石子数量小于5的时候,需要分别区分一下:仅当石子数=4的时候,我是不可能赢的。
那么,如果要解答这个问题,就需要看看:如何将上述的公式倒推到第一次怎么取。
其实只需要看看,对于最大可允许的i,我在第一次是否能够取到?取得到,那么我必胜;取不到,那么我必输。
就是这么说:如果最大的i为1,那么就是存在倒数第5个;此时,需要看看:是否能够在第一次取到倒数第5个数。倒数第5个数,如果此时有8个数,倒数第5个数就代表着是正数第4个数。
代码其实就很简单了:
public boolean canWinNim(int n) {
int w = (n-1)/4;
if(n-(w*4+1)>=3) return false;
return true;
//换言之,其实就是下面这个:return (n-1)%4!=3;
}
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:38.2 MB, 在所有 Java 提交中击败了5.26%的用户