题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1841
题目大意:大家都熟知的游戏,最开始有1元钱,开始回答问题,如果回答正确,奖金翻倍,如果答错,奖金为0,退出游戏。现在知道你答对每道题的概率在[p,1] 之间,你可以在任意时刻停止答题,问 你能得到的奖金的最大期望。
解题思路:设 你答对i 道题的期望奖金是 ans,又显然得你答对第i+1 道题的期望奖金是 2^(i+1)*p,那么如果ans> 2^(i+1)*p,你肯定不答题,反之你肯定选择答题,因此我们可以先求出 一个临界概率f,f=ans/2^(i+1);那么问题就来了,求fi的期望,要用到f(i+1),因此要逆推。
求出f后分情况讨论:
① 当f<p时,可知一定会继续做题,此时 作对的概率 取平均值 p=(1+p)/2;
② 当f>=p 时,在[p,f]范围内不继续做题,故 p=(p+f)/2*((f-p)/(1-p))(后面的部分为该区间占总区间的长度),在[f,1]范围内继续做题,故p=(1+f)/2*((1-f)/(1-p));
代码如下:
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int n;
double t,v[33];
void pow()
{
v[0]=1;
for(int i=1;i<=30;i++)
v[i]=v[i-1]*2;
}
void solve()
{
double ans=v[n];
for(int i=n-1;i>=0;i--)
{
double p=v[i]/ans;//计算临界概率
if(p<=t)
ans=(1+t)/2.0*ans;//如果临界概率<=t,则选择继续答题,此时的答对概率为(1+t)/2,即取概率中间值
else
ans=v[i]*(p-t)/(1-t)+ans*((1+p)/2.0)*((1-p)/(1-t));
//如果临界概率>t,则在[t,p]内,不继续答题,此时得到的钱为v[i],但是处在这个区间内的概率为(p-t)/(1-t);
//在[p,1]内,答对概率为(1+p)/2,在这个区间的概率为(1-p)/(1-t);
}
printf("%.3lf\n",ans);
}
int main()
{
pow();
while(~scanf("%d%lf",&n,&t))
{
if(n==0&&t==0) break;
solve();
}
return 0;
}