详细解题文章:
问题描述
Alice 和 Bob 进行一个猜数字的游戏。游戏中有 1 到 n 个数字,其中一个数字是中奖的,这个数字是等概率随机生成的。两人轮流猜一个 1 到 n 的数字,Alice 先猜。每完成一次猜测,主持人会大声说出刚刚的数字是猜小了还是猜大了或者猜中了,若猜中则猜的人赢下游戏。假设两人都是聪明的理智的,而且都知道对方是聪明的,求 Alice 获胜的概率。
输入输出格式
- 输入:一个正整数 n (1 ≤ n ≤ 1000)。
- 输出:保留 5 位小数输出 Alice 获胜的概率。
示例
- 输入:2
- 输出:0.50000
解题思路
为了求解 Alice 获胜的概率,我们需要分析两人在最优策略下的行为。由于 Alice 和 Bob 都是聪明的,他们会采取最优策略来最大化自己的获胜概率。
基本情况
-
当 n = 1 时:
- Alice 必然猜中,获胜概率为 1.00000。
-
当 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"));
}
}
解释
-
初始化:
dp[1] = 1.0
,因为当只有一个数字时,Alice 必然猜中。
-
状态转移:
- 对于每一个
i
,计算 Alice 在[1, i]
范围内获胜的最大概率。 - 对于每一个可能的
k
,计算 Alice 在猜k
时的获胜概率。 - 更新
dp[i]
为所有可能的k
中的最大值。
- 对于每一个
-
输出结果:
- 使用
String.format
将结果格式化为保留 5 位小数的字符串。
- 使用
结论
通过动态规划的方法,我们可以高效地计算出 Alice 在最优策略下获胜的概率。这个方法不仅适用于较小的 n,也适用于较大的 n(如题目中的 n ≤ 1000)。希望这篇文章对你理解这个问题有所帮助!