【博弈】A002_LC_石子游戏 IV(记忆化搜索 / 纯 dp)

一、Problem

Alice 和 Bob 两个人轮流玩一个游戏,Alice 先手。

一开始,有 n 个石子堆在一起。每个人轮流操作,正在操作的玩家可以从石子堆里拿走 任意 非零 平方数 个石子。

如果石子堆里没有石子了,则无法操作的玩家输掉游戏。

给你正整数 n ,且已知两个人都采取最优策略。如果 Alice 会赢得比赛,那么返回 True ,否则返回 False

输入:n = 7
输出:false
解释:当 Bob 采取最优策略时,Alice 无法赢得比赛。
如果 Alice 一开始拿走 4 个石子, Bob 会拿走 1 个石子,然后 Alice 只能拿走 1 个石子,Bob 拿走最后一个石子并赢得胜利(7 -> 3 -> 2 -> 1 -> 0)。
如果 Alice 一开始拿走 1 个石子, Bob 会拿走 4 个石子,然后 Alice 只能拿走 1 个石子,Bob 拿走最后一个石子并赢得胜利(7 -> 6 -> 2 -> 1 -> 0)。

提示:

1 <= n <= 10^5

二、Solution

方法一:

思路

如果当前剩余石子为 n n n,假设 Alice 现在要从 n 个石子中取 x 2 x^2 x2 个石子,那 Bob 下一轮只能在 n − x 2 n-x^2 nx2 中取平方个石子;

若存在一个状态 f [ n − x 2 ] = f a l s e f[n-x^2] = false f[nx2]=false 则证明 Bob 将要输掉比赛,也说明 f [ n ] f[n] f[n] 为 true(Alice 胜利状态)

也就是我们可以疯狂地让 Alice 尝试去 x 2 x^2 x2 个石子

class Solution {
     
    int n;
    boolean f[];
    boolean dfs(int n) {
     
        if (n == 0)
            return false;
        if (f[n]) 
            return f[n];
        for (int x = 1; x*x <= n; x++) {
     
            if (dfs(n-x*x) == false)
                return f[n] = true;
        }
        return f[n];
    }
    public boolean winnerSquareGame(int n) {
     
        this.n = n; f = new boolean[n+1];
        return dfs(n);
    }
}

复杂度分析

  • 时间复杂度: O ( n × s q r t ( n ) ) O(n × sqrt(n)) O(n×sqrt(n))
  • 空间复杂度: O ( n ) O(n) O(n)

你可能感兴趣的:(博弈)