UVA 10900 - So you want to be a 2n-aire?(概率DP)
题目链接 https://cn.vjudge.net/problem/UVA-10900
【题意】
赌博,刚开始有1元钱,主持人会问你n个问题,每次听到后你都有两个选择:一是放弃回答该问题,退出游戏并拿走奖金. 二是回答问题,如果回答正确奖金翻一倍,如果回答错误,立刻结束游戏,你一分钱都得不到. 如果你把所有的问题都回答完了,那么你可以获得 元的奖金. 当然回答问题是有风险的,每次听到问题之后,你可以知道答对它的概率,主持人会随机问问题,所以可以认为每个问题被答对的概率在 之间均匀分布,输入整数和实数 你的任务是求出在最优策略下,拿走奖金的期望值,最优策略指的是让奖金的期望值尽量大.
【思路】
思维很强的一道题,不看讲解感觉无从下手. 首先要设 表示答对了 道题之后最大的奖金期望,那么可以肯定的是 ,这是递推的边界. 然后我们考虑递推, 表示已经答对了 道题,现在有两种选择,如果不去回答第 道题,那么期望就是 ,如果回答这道题,假设答对的概率为 ,那么对应的期望就是 . 所以就要根据这两种不同的选择能带来的不同收益来决定是否去回答这道题了,也就是去比较 和 的大小关系,即比较 和 的关系,记
分两种情况讨论,
如果 说明选择答题的收益一定比拍屁股走人多,所以就选择答题,平均答对的概率是
如果 还要再细分,因为
- 当 时, 即 选择退出游戏会更好,有 的概率会是这种情况
- 当 时, 即 选择继续答题会更好,有 的概率会是这种情况
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=35;
const double eps=1e-6;
int n;
double t;
double dp[maxn];
int main(){
while(scanf("%d%lf",&n,&t)==2){
if(0==n && fabs(t)<eps) break;
dp[n]=(1<<n);
for(int i=n-1;i>=0;--i){
if(t*dp[i+1]>=(1<<i)){
dp[i]=(1+t)/2*dp[i+1];
}
else{
double p0=(1<<i)/dp[i+1];
dp[i]=((p0-t)/(1-t))*(1<<i)+((1-p0)/(1-t))*(p0+1)/2*dp[i+1];
}
}
printf("%.3lf\n",dp[0]);
}
return 0;
}