• [LeetCode 1025.] 除数博弈


    LeetCode 1025. 除数博弈

    博弈问题,非常有趣。

    题目描述

    Alice and Bob take turns playing a game, with Alice starting first.

    Initially, there is a number N on the chalkboard. On each player's turn, that player makes a move consisting of:

    • Choosing any x with 0 < x < N and N % x == 0.
    • Replacing the number N on the chalkboard with N - x.

    Also, if a player cannot make a move, they lose the game.

    Return True if and only if Alice wins the game, assuming both players play optimally.

    Example 1:

    Input: 2
    Output: true
    Explanation: Alice chooses 1, and Bob has no more moves.

    Example 2:

    Input: 3
    Output: false
    Explanation: Alice chooses 1, Bob chooses 1, and Alice has no more moves.

    Note:

    1. 1 <= N <= 1000

    解题思路

    这道题是说,给定一个初值 N,然后先手给出 N 的一个因数 x,再用 N-x 替换数字,交由对方操作;直到一方拿到 1 再也找不到比自身小的因数算是输掉比赛。
    双方都足够聪明,会选取对自己最有利的操作,给出任意一个 N 会是输是赢。

    思路一:DP

    我们去枚举每一个因子,如果存在一个因子可以让对方输掉比赛,我们也就能赢;否则我们就要输掉比赛。

    思路二:数学构造法

    如果我们就是最聪明的人,能一下子找到最佳策略,那我们也可以很快直到怎么操作怎么赢。

    注意到:

    1. 拿到 1 的必输,谁能最先拿到 2 谁赢;
    2. 拿到奇数的,因为因数只有奇数,对手必将获得偶数;
    3. 拿到偶数的,只要一直选1这个因数,对手将一直被迫拿奇数,自己一直稳拿偶数,直到拿到 2 获得胜利。

    结论也就来了,拿到偶数的,够聪明就一直用因子 1,稳赢;拿到奇数的,选哪个奇数都是输!

    你以为人定胜天,其实你根本没得选,开局的时候输赢就已经定了……

    参考代码

    两种思路的代码如下:

    /*
     * @lc app=leetcode id=1025 lang=cpp
     *
     * [1025] Divisor Game
     */
    
    // @lc code=start
    class Solution {
    public:
    /*
        bool divisorGame(int N) {
            vector<bool> dp(N+1);
            dp[1] = false;
            dp[2] = true;
            dp[3] = false;
            for (int i=4; i<=N; i++) {
                bool canWin = false;
                for (int j=1; j<i; j++) {
                    if (i % j == 0) {
                        if (!dp[i-j]) {
                            canWin = true;
                            break;
                        }
                    }
                }
                dp[i] = canWin;
            }
            return dp[N];
        } // AC
    */
        bool divisorGame(int N) {
            return (N % 2) == 0;
        } // AC
    };
    // @lc code=end
    
  • 相关阅读:
    linux使用jstack来找出死循环的java代码
    Dubbo的几种序列化协议
    上传新项目到GitLab
    PI Network项目,手把手教快速挖Pi币
    Oracle数据导出、导入
    如何实现表单标题两端对齐
    cookie 操作记录& vuex 中页面刷新 state 数据丢失的问题
    FCSAN存储与服务器关联映射后在服务器端如何识别操作
    修改密码报-bash: !@#***": event not found
    springboot整合logstash
  • 原文地址:https://www.cnblogs.com/zhcpku/p/14510923.html
Copyright © 2020-2023  润新知