1025 除数博弈
爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。
最初,黑板上有一个数字 N
。在每个玩家的回合,玩家需要执行以下操作:
选出任一 x
,满足 0 < x < N
且 N % x == 0
。
用 N - x
替换黑板上的数字 N
。
如果玩家无法执行这些操作,就会输掉游戏。
只有在爱丽丝在游戏中取得胜利时才返回True
,否则返回 false
。假设两个玩家都以最佳状态参与游戏。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/divisor-game
示例 1:
输入:2
输出:true
解释:爱丽丝选择 1,鲍勃无法进行操作。
示例 2:
输入:3
输出:false
解释:爱丽丝选择 1,鲍勃也选择 1,然后爱丽丝无法进行操作。
力扣中已经有许许多多的题解了,相信很多也比我写的详细,在这里只是想自己把自己的思路记录下来,汇总到一起,以便日后复习巩固。
法一:
奇偶性判断
由于爱丽丝先手开局,当NNN为偶数时,爱丽丝选择x=1x = 1x=1,则鲍勃遇到的 为奇数,由于N%x==0N \% x == 0N%x==0中当NNN为奇数时,xxx必定为奇数,所以此时N−xN-xN−x又为偶数。爱丽丝继续选择111,鲍勃得到的又是奇数。直到最后爱丽丝得到222,爱丽丝选择111,鲍勃无法操作。爱丽丝取胜。
当NNN为奇数时,爱丽丝则变为了上面情况的鲍勃,最后一定失败。
class Solution {
public:
bool divisorGame(int N) {
if (N%2==0) return true;
return false;
}
};
法二:动态规划
用dp[i]dp[i]dp[i]来表示当初始值是iii时爱丽丝的输赢情况。dp[0]=0;dp[1]=0;dp[2]=1;dp[0] = 0; dp[1]=0;dp[2]=1;dp[0]=0;dp[1]=0;dp[2]=1;
dp[i]dp[i]dp[i]的判断和前面有关系,当iii前面的j∈[1,i−1]j\in[1,i-1]j∈[1,i−1]中有i%j==0
并且dp[i-j]==0
(因为下一步鲍勃得到的值是i−ji-ji−j,dp[i−j]=0dp[i-j]=0dp[i−j]=0说明鲍勃是输的) 则dp[i]=1dp[i]=1dp[i]=1,否则dp[i]=0dp[i]=0dp[i]=0。
class Solution {
public:
bool divisorGame(int N) {
if (N<=1) return false;
vector<int> v(N+1);
v[0]=0,v[1]=0,v[2]=1;
for(int i = 3;i <= N; i++)
{
v[i]=0;
for(int j=1;j<i;j++)
{
if (i%j==0&&v[i-j]==0)
{
v[i]=1;break;//有一个使爱丽丝赢得情况即可
}
}
}
return v[N]==1;
}
};