zoukankan      html  css  js  c++  java
  • [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
    
  • 相关阅读:
    dotnet 控制台读写 Sqlite 提示 no such table 找不到文件
    dotnet 控制台读写 Sqlite 提示 no such table 找不到文件
    dotnet 控制台 Hangfire 后台定时任务
    dotnet 控制台 Hangfire 后台定时任务
    dotnet 获取指定进程的输入命令行
    dotnet 获取指定进程的输入命令行
    PHP sqrt() 函数
    PHP sinh() 函数
    PHP sin() 函数
    PHP round() 函数
  • 原文地址:https://www.cnblogs.com/zhcpku/p/14510923.html
Copyright © 2011-2022 走看看