Millionaire-白书-概率dp

学了,记录下

你被邀请到某个电视节目中去玩下面这个游戏。一开始你有x元钱,接着进行m轮赌博,每一轮,可以将所持的任意一部分作为赌注,赌注不光可以是整数,也可以是小数,一分钱不押或全押都没有关系,每一轮都有p的概率可以赢,赢了赌注就好翻倍,输了赌注就没了,如果你最后有100万以上的钱的话,就可以把钱带回家。请计算当你采取最优策略时,获得100万以上的钱并带回家的概率。 0<=p<=1.0,1<=1<=1000000,1<=m<=15 样例输入: M,p, x 输入 :1 0.5 500000     输出 0.500000(一开始九全押上) 输入: 3,0.75 600000  输出0.843750

先计算样例:

从60000中拿出2500,如果赢了,再拿出75,可以 两轮赢0.75*0.75 ,要是第二轮输了,三轮赢全堵上赢0.75*0.25*0.75

或者第一轮输了,后面两轮全赢。三轮赢0.25*0.75*0.75。

白书解析:对于赌博,因为每次都能下注的金额是无限种可能的,所以,要将无限化有限(化连续为离散)

对于最后一次赌博:

1.  本金>= 1000 000   概率为1(直接就走了)

2.  本金>=5000 00     概率为P(赢了有,输了没)

3.  本金<5000 00     概率为0  (不管输赢都没有1000 000)  

最后两轮:

1.本金  >=1000 000   概率为1

2. 本金 >=7500 00    概率为:P*P(两次都输才会输2500 00+5000 00)  

3. 本金 >=5000 00    概率为:P(赢一次直接走,输了必定不可能到1000 000)

4. 本金 >=2500 00    概率为:(1-P)*(1-P)必须两次都赢

5. 本金 <2500 00     概率为:0   别想了 . . . .

某个范围内,即使所持的钱数不同,最后可以带钱回家的概率也是相同的  

M轮 考虑 2^M+1 种情况。因此将金额进行离散化分段处理。

设dp[r+1][i]为进行到第r+1轮,现有i段钱能赢得百万的概率?那什么是最优策略呢?在第r轮要对拿出多少去赌好呢?。

不知道要拿多少,那我们枚举吧,假设r轮要拿出j个段钱去赌

那么dp[r+1][i]=max(dp[r][i+j]*p+dp[r][i-j]*(1-p))    j=min( i,n-i);

因为i+j<=n;i-j>=0; 所以 j<=i,j<n-i;

所以最后的答案就是dp[M][X所在的段]

#include<iostream>
#include<cstring>
using namespace std;
 
typedef long long ll;
const int MAXN = 15;
 
double dp[18][(1<<MAXN)+1];//dp[i][j]代表在运行了i伦的情况下有钱数j获胜的概率 
int main(){
    int M,X;
    double P;
    scanf("%d %lf %d",&M,&P,&X);
    int n = 1<<M; 
    dp[0][n] = 1.0;  
   int m=(ll)X*n/1e6;
    for(int r=0;r<M;r++){           //r是赌博的轮数,0代表还没开始,M代表最后
        for(int i=0;i<=n;i++){      //i是情况序号,代表百万数据的 i/2^m 
            int step = min(i,n-i);
            double t =0.0;int pt;
            for(int j=0;j<=step;j++){//从i个钱中拿出j个去赌,赢了后变i+j个,输了变i-j个,从中中出最优划分。 
               // if(t<dp[r][i+j]*P+dp[r][i-j]*(1-P))t=dp[r][i+j]*P+dp[r][i-j]*(1-P),pt=j; 观察最优策略 
			   dp[r+1][i] =max(dp[r+1][i],dp[r][i+j]*P+dp[r][i-j]*(1-P)) ; 
            }
            cout<<"dp["<<r+1<<"]["<<i<<"]="<<dp[r+1][i]<<"="<<dp[r][i+pt]<<"*"<<P<<"+ "<<dp[r][i-pt]<<"*"<<(1-P)<<","<<pt<<endl;
        }
    } 
    printf("%.6f\n",dp[M][m]);
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值