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\n",Solve(n,t)); } return 0; }