1025. 除数博弈

题干

爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。

最初,黑板上有一个数字 N 。在每个玩家的回合,玩家需要执行以下操作:

选出任一 x,满足 0 < x < N 且 N % x == 0 。

用 N - x 替换黑板上的数字 N 。

如果玩家无法执行这些操作,就会输掉游戏。

只有在爱丽丝在游戏中取得胜利时才返回 True,否则返回 False。假设两个玩家都以最佳状态参与游戏。

 

示例 1:

输入:2

输出:true

解释:爱丽丝选择 1,鲍勃无法进行操作。

示例 2:

输入:3

输出:false

解释:爱丽丝选择 1,鲍勃也选择 1,然后爱丽丝无法进行操作。

 

提示:

1 <= N <= 1000

 

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/divisor-game

 

思路

方法一,用数学归纳法,找规律。

N=1,false

N=2,true

N=3,false

……

发现奇数false,偶数true

public boolean divisorGame(int N) {
  if(N%2==0){
    return true;
  }
  else{
    return false;
  }
}

方法二,动态规划

用dp数组来记录各个N值时,爱丽丝是否赢得了胜利

本题的状态转移方程的思路如下

把每个N的因子与它本身进行除法,根据题意,两人都是最佳状态。因此但凡有一个因子相除以后的状态下是爱丽丝因的胜利,则她一定会选择使自己获胜的银子,则可以记录为1,否则记录为0

class Solution {
    public boolean divisorGame(int N) {
        /*
        dp[n]=1表示爱丽丝获胜
        dp[n]=0表示爱丽丝失败
        */
        int[] dp=new int[N+1];
        if(N==1){
            dp[1]=0;
        }
        else if(N==2){
            dp[1]=0;
            dp[2]=1;
        }
        else if(N>=3){
            dp[1]=0;
            dp[2]=1;
            for(int i=3;i<=N;i++){
                // dp[i]=-1;
                for(int j=1;j<=i/2;j++){
                    if(i%j==0){//如果i被j被整除
                        if(dp[i-j]==1&&dp[i]!=1){
                            dp[i]=0;
                        }
                        else if(dp[i-j]==0){
                            dp[i]=1;
                        }
                    }
                }
            }
        }

        if(dp[N]==0){
            return false;
        }
        else if(dp[N]==1){
            return true;
        }
        return false;
    }
}

 

posted @ 2020-12-26 18:30  Heinrich♣  阅读(128)  评论(0编辑  收藏  举报