题目地址:
http://acm.hdu.edu.cn/showproblem.php?pid=1145
题目描述:
1 0.5 1 0.3 2 0.6 24 0.25 0 0
1.500 1.357 2.560 230.138
题意:
一个人有1$钱,然后答n道题,可以不答带原有奖金离开,或者答题获得双倍奖金然后继续答题。问最佳收益是多少。
题解:
此题主要是有这样的决策,面对第i+1道题时到底是答还是不答,已经答完i道题的情况下。代码:
明显答还是不答要看i道题的后一题i+1道题的期望收益,如果总体期望收益大于i道题的,我干吗不答呢??
所以就有假设:
p*ex[i+1] > 2^i, 答
左侧p表示i+1题答对的概率,ex[i+1]表示i+1题以及考虑后面题的最佳期望收益奖金(最佳是表示不仅考虑了i+1,还考虑了后面的i+2,i+3......,n的答题情况的综合期望,代码倒推循环的原因也在于此,所以ex[0]是综合了第1道题 到 第n道题的综合最佳收益奖金,所以我们最终输出ex[0])
p*ex[i+1] < 2^i,不答 (我答了题奖金反而减少)
由此我们可以得出一个临界概率,bp=2^i/ex[i+1]
然后注意t值不是我们答题的概率,t只是限定我们答题概率的变化边界(一开始读题就误导t的含义了),我们答题的概率是[t,1)
边界概率bp < t: 本题的最佳收益是 ex[i] = (1+t)/2 * ex[i+1]
说明随便答,p随意取[t,1)的值都是 p*ex[i+1] > 2^i 所以直接用平均概率去答题就ok了,注意这个平均概率这个平均是(起点 + 终点)/2 的意思,直接画个一维数轴就行了。也就是说答i题的收益是 p*ex[i+1] 而p我们取的是平均的概率即p=(1+t)/2
边界概率bp > t: 本题的最佳收益是 ex[i] = (bp-t)/(1-t) * 2^i + (1-bp)/(1-t) * (1+bp)/2 * ex[i+1]
这里最好画个数轴要清楚点,当bp > t时 ,在数轴上 bp 肯定在[t,1)之间,那么[t,bp)表明不答i+1题,[bp,1)表明答i+1题,注意大分母是1-t,不是1,看下概率密度的概念,画个数轴就知道了。
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> using namespace std; double ex[30+5]={0.0};//best expect double mon[30+5]={0.0};//best money double t=0.0;//probability p is t < p < 1 int n=0;//number of question double bp=0.0;//boundary probability, if p > bp then get in the question otherwise get out the question int main() { mon[0]=1;//after answer 0 question,the index begin with 1 for(int i=1;i<=30;i++) { mon[i]=mon[i-1]*2; } while(scanf("%d%lf",&n,&t)!=EOF&&(n>0)) { ex[n]=mon[n]; //from ex[i+1] get the ex[i],ex[0] is our answers for(int i=n-1;i>=0;i--) { bp=mon[i]/ex[i+1];// 2^i/ex[i+1] is the boundary probability ==> bp * ex[i+1] > 2^i if(bp<=t)//bp is not in [t,1) range, all p in [t,1) will let the p * ex[i+1] >2^i { ex[i]=(1+t)/2 * ex[i+1]; } else// E = p*x + (1-p)*y { ex[i]=(bp-t)/(1-t) * mon[i] + (1-bp)/(1-t) * (1+bp)/2 * ex[i+1]; } } printf("%.3lf\n",ex[0]); } return(0); }