leetcode:除数博弈

题目来源:力扣

这是我做的第一道动态规划题目,今天看了一上午算法导论动态规划那一章,下午准备检验一下自己的理解.虽然这道题难度为简单级别,但在自己独立思考下做出来了,感觉美滋滋!

题目描述:

爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。
最初,黑板上有一个数字 N 。在每个玩家的回合,玩家需要执行以下操作:
选出任一 x,满足 0 < x < N 且 N % x == 0 。
用 N - x 替换黑板上的数字 N 。
如果玩家无法执行这些操作,就会输掉游戏。
只有在爱丽丝在游戏中取得胜利时才返回 True,否则返回 false。假设两个玩家都以最佳状态参与游戏。
==========================================================
示例 1:
输入:2
输出:true
解释:爱丽丝选择 1,鲍勃无法进行操作。
示例 2:
输入:3
输出:false
解释:爱丽丝选择 1,鲍勃也选择 1,然后爱丽丝无法进行操作。
==========================================================

审题:

由于题目的主要标签是动态规划,因此我直接尝试从动态规划的角度去思考该问题.
题目中的关键信息是最后一句:两个玩家都以最佳状态参与游戏.我们知道,动态规划算法通常与最优解问题相关.当然要使用动态规划算法来解决问题,还需要检查其他必要条件是否满足,后面一一进行分析.

该问题中,玩家以最佳状态参与游戏意味着玩家会在每一步选择最好的结果,以保证其取得最终胜利.我们使用布尔数组P[]表示存储玩家在最优状态下参与游戏的最优结果.P[i] = true表示若当前黑板上数字为i,则在两个玩家都以最佳状态参与游戏的情况下,当前玩家会取得胜利.反之,则表示当前玩家最终会失败.

我们首先分析该问题是否具有最优子结构形式.由于两个玩家都以最佳状态参与游戏,因此该问题天然地即是最优子结构形式.如果当前黑板上数字为N,假设当前用户的最优选择为x,则如果后续玩家都已最佳状态参与游戏,则有:P[N]=!P[Nx]P[N] = !P[N-x],表示如果对手能够赢得最终胜利,则当前用户最终将失败,如果对手最终失败,则当前用户将赢得最终胜利.如果当前用户无法执行有效选择,则其最终将失败.

接下来分析该问题的子问题是否具有重叠,假设当前黑板上数字为N, 则为了确定最优的选择,我们需要判断每一可能的x(其中N%x==0),计算P[N-x].因此,在计算P[N-x1]时,我们需要计算P[K], K<N-x1, 而当计算P[N-x2]时,我们也要计算P[K], K<N-x2.因此子问题存在重叠结构.

在以上分析中,我们如果黑板上有数为N,则有N个子问题,P[1], P[2], …P[N], 我们可以使用自底向上的动态规划算法解决该问题.

java算法:

class Solution {
    //假设布尔数组P存储用户最优选择下最终胜利结果.
    //p[i] = true表示如果当前用户的选择范围为0~i,则在自己与对手均以最佳状态参与时,她将胜利
    //p[i] = false表示如果当前用户的选择范围为0~i,则在自己与对手均以最佳状态参与时,她将失败
    
    //当N=1时,用户无法选择有效值,因此p[1] = false
    //当N=2时,该用户当前步选择1,对手最优结果为p[1] = false,因此该用户胜利,因此p[2] = true
    //当N=3时,该用户当前步只能选择2,对手最优结果为p[1] = true,因此该用户失败,因此p[3] = false
    //当N=4时,该用户当前步可以选择1,2,如果选择1,对手最优结果为p[3] = false, 如果选择2,对手最优结果为p[2] = true,
    //因此他当前步最优选择为1,p[4] = true
    

    public boolean divisorGame(int N) {
        boolean[] play = new boolean[N+1];
        play[1] = false;

        for(int i = 2; i <= N; i++){
            for(int j = 1; j < i; j++){
                if(i % j == 0){ //如果可以选择j
                    if(play[i-j] == false) //如果下一步对手的最优执行结果为false,则当前步执行结果为true
                        play[i] = true;            
                }
            }
        }
        return play[N];
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章