UVA 10900 So you want to be a 2n-aire? (概率dp)

题意:玩家初始的金额为1;给出n,表示有n道题目;t表示说答对一道题目的概率在t到1之间均匀分布。

   每次面对一道题,可以选择结束游戏,获得当前奖金;或者回答下一道问题,答对的话奖金翻倍,答错的话结束游戏没有奖金,求玩家使用最优策略赢的奖金的期望值的最大值。

题解:遇见第(i+1)个题目的时候有两种选择:结束这个题,获得2^i的钱;回答这个题目,答对就获得2^(i+1)的钱

   因此设dp[i]表示答对第i个题,面对第(i+1)个题可以获得的期望钱数,则dp[i]=2^i * 不去回答这个题的概率 + dp[i+1] * 回答这个题的概率 * 答对这个题的概率

   答对这个题的概率 p0=max(t,(2^i)/dp[i+1])

    (2^i)/dp[i+1]表示回答第 i+1 个题需要这么大的概率才能获得更大的价值;max表示如果t大于这个概率,则我们就只能选择t(注意题目给定的概率为范围,最小的概率为t)

    回答这个题的概率 p1=(1-p0)/(1-t)(注意t=1的情况);就是说给定的概率如果太小,那么就有可能在某些情况下不去回答这个题

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=1<<28;
const ll INF=1LL<<60;
const double Pi=acos(-1.0);
const int Mod=1e9+7;
const int Max=200010;
double dp[Max];//答对第i题可以获得的期望奖金
double Solve(int n,double t)
{
    dp[n]=(1<<n);//答对第n题会得到这么多钱
    for(int i=n-1;i>=0;--i)
    {
        double p0=max(t,(1<<i)/dp[i+1]);//答题才可能获得更高钱的概率与最低概率求最大(如果最低概率大了,就需要取最低概率)
        double p1;//去答题的概率的可能性
        if(sgn(1-t)!=0)
        p1=(1-p0)/(1-t);
        else
        p1=1;
        dp[i]=p1*dp[i+1]*(p0+1)/2+(1-p1)*(1<<i);//分为答题(答题的概率*答对的收获*答对概率) + 不答题
    }
    return dp[0];
}
int main()
{
    int n;
    double t;
    while(~scanf("%d %lf",&n,&t))
    {
        if(n==0&&zero(t))
        break;
        printf("%.3f
",Solve(n,t));
    }
    return 0;
}