1 条题解
-
0
题意分析
玩家初始奖金为1美元,需回答个问题。每回答一个问题:
- 若选择回答且答对,奖金翻倍;若答错,奖金清零并结束游戏。
- 若选择不回答,可保留当前奖金并结束游戏。
每个问题的答对概率是在区间内均匀分布的随机变量。玩家需采用最优策略(即根据当前决定是否回答),使得期望奖金最大化。
解题思路
-
动态规划思想:
- 从最后一个问题向前逆推,计算在每个问题处的最优决策(回答或放弃)。
- 定义为从当前问题开始到游戏结束的最大期望奖金。
-
临界概率判断:
- 对于每个问题,存在一个临界概率,其中是当前问题的奖金。
- 当时,所有可能的都满足,此时回答问题的期望更高。
- 当时,需分区间计算期望:
- 若,选择放弃,获得奖金。
- 若,选择回答,期望奖金为。
-
数学公式推导:
- 当时,期望奖金为。
- 当时,期望奖金为$\frac{v[i] \times (p-t) + ans \times \frac{1+p}{2} \times (1-p)}{1-t}$。
代码解释
#include <cstdio> #include <cmath> double v[31]; // 存储奖金值v[i] = 2^i // 预处理2的幂次方 void precompute() { v[0] = 1.0; for(int i = 1; i <= 30; ++i) v[i] = v[i-1] * 2; } // 计算最优策略下的期望奖金 double solve(int n, double t) { double ans = v[n]; // 初始化为最后一道题的奖金 // 从倒数第二个问题向前递推 for(int i = n-1; i >= 0; --i) { double p = v[i] / ans; // 计算临界概率 if(p <= t) { // 所有可能的p都满足p >= v[i]/ans,选择回答 ans = (1.0 + t) / 2.0 * ans; } else { // 分区间计算期望 double case1 = v[i] * (p - t) / (1.0 - t); // 放弃回答的期望 double case2 = ans * (1.0 + p) / 2.0 * (1.0 - p) / (1.0 - t); // 继续回答的期望 ans = case1 + case2; } } return ans; } int main() { precompute(); int n; double t; // 处理输入 while(scanf("%d%lf", &n, &t) == 2) { if(n == 0 && t == 0) break; printf("%.3lf\n", solve(n, t)); } return 0; }
关键细节
-
预处理:
- 预先计算的值,存储在数组中,避免重复计算。
-
逆推过程:
- 从最后一个问题开始向前计算,每次根据当前奖金和后续期望奖金计算最优决策。
-
临界概率处理:
- 当时,所有可能的都使得回答问题的期望更高。
- 当时,需根据的分布分区间计算期望,综合考虑放弃和回答两种情况。
-
精度控制:
- 使用
printf("%.3lf\n", ...)
确保输出结果保留三位小数。
- 使用
复杂度分析
- 时间复杂度:,其中是问题数量。
- 空间复杂度:,仅需常数级额外空间。
该算法通过逆推和数学期望的计算,高效地解决了最优策略选择问题,适用于题目给定的的范围。
- 1
信息
- ID
- 1651
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者