leetcode-dp-博弈问题-除数博弈

package dp.divisorGame;

/**
 * 1025. 除数博弈
 * 爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。
 * <p>
 * 最初,黑板上有一个数字 N 。在每个玩家的回合,玩家需要执行以下操作:
 * <p>
 * 选出任一 x,满足 0 < x < N 且 N % x == 0 。
 * 用 N - x 替换黑板上的数字 N 。
 * 如果玩家无法执行这些操作,就会输掉游戏。
 * <p>
 * 只有在爱丽丝在游戏中取得胜利时才返回 True,否则返回 False。假设两个玩家都以最佳状态参与游戏。
 * <p>
 * <p>
 * <p>
 * 示例 1:
 * <p>
 * 输入:2
 * 输出:true
 * 解释:爱丽丝选择 1,鲍勃无法进行操作。
 * 示例 2:
 * <p>
 * 输入:3
 * 输出:false
 * 解释:爱丽丝选择 1,鲍勃也选择 1,然后爱丽丝无法进行操作。
 * <p>
 * <p>
 * 提示:
 * <p>
 * 1 <= N <= 1000
 * 通过次数78,570提交次数110,824
 */
public class divisorGame {
    /**
     * N = 1时,很明显Alice无法写任何数,失败;
     * N = 2时,Alice只能写1,于是根据上面的结论,Bob无法写任何数,失败,Alice获胜;
     * N = 3时,3的唯一小于它的约数为1,Alice只能写2,于是根据上面的结论,Alice失败;
     * N = 4时,Alice可以写3,于是Bob失败,她获胜;
     * 总而言之,当N为奇数时,Alice失败,而当N为偶数时,Alice获胜。
     * <p>
     * 递推公式 i%j==0 && !dp[i-j]
     * 解释 i代表从i到N,j代表从1到N-1,如果存在合适的除数,就判断N-i的那个位置后手人的状态。
     *
     * @param n
     * @return
     */
    public static boolean divisorGame(int n) {
        if (n == 1) {
            return false;
        }
        boolean[] dp = new boolean[n + 1];
        dp[1] = false;
        for (int i = 2; i <= n; i++) {
            for (int j = 1; j < i; j++) {
                if (i % j == 0 && !dp[i - j]) {
                    dp[i] = true;
                }
            }
        }
        return dp[n];
    }

    public static void main(String[] args) {
        System.out.println(divisorGame(3));
    }
}


posted @ 2022-01-13 10:19  小傻孩丶儿  阅读(31)  评论(0编辑  收藏  举报