UVa 10900 So you want to be a 2n-aire? (概率DP,数学)

题意:一 个答题赢奖金的问题,玩家初始的金额为1,给出n,表示有n道题目,t表示说答对一道题目的概率在t到1之间,每次面对一道题,可以选择结束游戏,

获得当 前奖金;回答下一道问题,答对的概率p在t到1之间,答对的话奖金翻倍,答错的话结束游戏,没有奖金,求玩家赢的奖金的期望值的最大值。

析:首先是求期望,那就和平均值差不多,我们来分析第 i 道题时,两个情况,要么回答,要么不回答,如果不回答那么就是2^i,如果回答概率是p * 下一个题的概率,

那么比较期望谁的大,如果p * ans > 2 ^  i,那么就回答,那么我们只要求出临界值就好,也就是 p0 = 2 ^ i / ans,再利用全期望公式,加起来就好。

如果p0 < t,那么他一定回答这个题,如果小于等于,有两个情况,一种就是[t, p0], 一种是[p0, 1],加起来就好。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
using namespace std ;

typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f3f;
const double eps = 1e-8;
const int maxn = 1e4 + 5;
const int mod = 1e9 + 7;
const int dr[] = {0, 0, -1, 1};
const int dc[] = {-1, 1, 0, 0};
int n, m;
inline bool is_in(int r, int c){
    return r >= 0 && r < n && c >= 0 && c < m;
}
double ans[35];
double t;

double solve(){
    if(fabs(t - 1.0) < eps)  return ans[n];

    double aans = ans[n];
    for(int i = n-1; i >= 0; --i){
        double p0 = ans[i] / aans;
        double p1 = (p0-t)/(1-t);

        if(p0 < t)  aans = (1+t) / 2 * aans;
        else aans = ans[i] * p1 + (p0+1)/2*aans * (1-p1);
    }
    return aans;
}

int main(){
    ans[0] = 1.0;
    for(int i = 1; i < 32; ++i)
        ans[i] = ans[i-1] * 2.0;
    while(scanf("%d %lf", &n, &t) == 2){
        if(!n && !t)  break;
        printf("%.3lf
", solve());
    }
    return 0;
}
原文地址:https://www.cnblogs.com/dwtfukgv/p/5746760.html