java题解"策略大师: 小I与小w的数字猜谜挑战" | 豆包MarsCode AI刷题

3 阅读3分钟

详细解题文章:

问题描述

Alice 和 Bob 进行一个猜数字的游戏。游戏中有 1 到 n 个数字,其中一个数字是中奖的,这个数字是等概率随机生成的。两人轮流猜一个 1 到 n 的数字,Alice 先猜。每完成一次猜测,主持人会大声说出刚刚的数字是猜小了还是猜大了或者猜中了,若猜中则猜的人赢下游戏。假设两人都是聪明的理智的,而且都知道对方是聪明的,求 Alice 获胜的概率。

输入输出格式

  • 输入:一个正整数 n (1 ≤ n ≤ 1000)。
  • 输出:保留 5 位小数输出 Alice 获胜的概率。

示例

  • 输入:2
  • 输出:0.50000

解题思路

为了求解 Alice 获胜的概率,我们需要分析两人在最优策略下的行为。由于 Alice 和 Bob 都是聪明的,他们会采取最优策略来最大化自己的获胜概率。

基本情况
  1. 当 n = 1 时

    • Alice 必然猜中,获胜概率为 1.00000。
  2. 当 n = 2 时

    • Alice 有 50% 的概率猜中,获胜概率为 0.50000。
一般情况

当 n > 2 时,Alice 会选择一个数字 k 进行猜测。假设 Alice 猜的是 k:

  • 如果 k 是中奖数字,Alice 获胜。
  • 如果 k 小于中奖数字,Bob 将在 [k+1, n] 范围内继续猜测。
  • 如果 k 大于中奖数字,Bob 将在 [1, k-1] 范围内继续猜测。

Alice 的最优策略是选择一个 k,使得她在两种情况下获胜的概率最大。

动态规划

我们可以使用动态规划来解决这个问题。设 dp[i] 表示在 [1, i] 范围内 Alice 获胜的概率。

状态转移方程

对于每一个 i,Alice 会选择一个 k,使得她的获胜概率最大。因此,我们有:

[ dp[i] = \max_{1 \leq k \leq i} \left( \frac{1}{i} + \frac{i-k}{i} (1 - dp[k-1]) + \frac{k-1}{i} (1 - dp[i-k]) \right) ]

其中:

  • (\frac{1}{i}) 是直接猜中的概率。
  • (\frac{i-k}{i} (1 - dp[k-1])) 是猜大了的情况下的概率。
  • (\frac{k-1}{i} (1 - dp[i-k])) 是猜小了的情况下的概率。

实现

以下是具体的实现代码:

public class Main {
    public static String solution(int n) {
        if (n == 1) {
            return "1.00000";
        }

        double[] dp = new double[n + 1];
        dp[1] = 1.0;

        for (int i = 2; i <= n; i++) {
            double maxProb = 0.0;
            for (int k = 1; k <= i; k++) {
                double prob = 1.0 / i;
                if (k > 1) {
                    prob += (k - 1) / (double) i * (1 - dp[k - 1]);
                }
                if (k < i) {
                    prob += (i - k) / (double) i * (1 - dp[i - k]);
                }
                maxProb = Math.max(maxProb, prob);
            }
            dp[i] = maxProb;
        }

        return String.format("%.5f", dp[n]);
    }

    public static void main(String[] args) {
        System.out.println(solution(2).equals("0.50000"));
        System.out.println(solution(931).equals("0.50054"));
        System.out.println(solution(924).equals("0.50000"));
        System.out.println(solution(545).equals("0.50092"));
    }
}

解释

  1. 初始化

    • dp[1] = 1.0,因为当只有一个数字时,Alice 必然猜中。
  2. 状态转移

    • 对于每一个 i,计算 Alice 在 [1, i] 范围内获胜的最大概率。
    • 对于每一个可能的 k,计算 Alice 在猜 k 时的获胜概率。
    • 更新 dp[i] 为所有可能的 k 中的最大值。
  3. 输出结果

    • 使用 String.format 将结果格式化为保留 5 位小数的字符串。

结论

通过动态规划的方法,我们可以高效地计算出 Alice 在最优策略下获胜的概率。这个方法不仅适用于较小的 n,也适用于较大的 n(如题目中的 n ≤ 1000)。希望这篇文章对你理解这个问题有所帮助!