題意:
剛開始持有x元錢
將進行M輪賭博
每輪贏得概率爲P
贏則賭注翻倍,輸則賭注全無
問最優策略下賺得1000000元錢(或以上)的概率。
思路:
搜索:
double chance(int cengshu, int money)
{
if(cengshu== M )
{
if(money>=1000000)
return 1;
if(money>=500000)
return 0.5;
return 0;
}
double chance_now = 0.0;
for(int I = 0; i<= money; i++)
chance_now=min(chance_now,P*chance(cengshu+1,money+i)+(1-P)*chance(cengshu+1,money-i));
returnchance_now;
}
定義dp[i][j]爲初始賭資2^j元經過i輪賭博賭資擴大到2^M元的概率
令x = min(j, 2^M)
則dp[i+1][j] = max{P*dp[i][j+y] + (1-P)*dp[i][j-y]} (0<=y<=x)
發現在轉移過程之中僅僅需要上層i的值,所以只用兩層數組記錄即可。
P.S.注意考慮錢數與概率的對應關係,這是離散化處理的保證
#include <stdio.h>
#include <algorithm>
#include <string.h>
#define LL long long
using namespace std;
double dp[2][1<<15 + 1];
int main()
{
int M, X;
double P;
while(scanf("%d %lf %d", &M, &P, &X)==3)
{
memset(dp, 0, sizeof(dp));
int n = 1<<M;
double *fomer = dp[0];
double *later = dp[1];
fomer[n] = 1;
for (int i = 0; i < M; ++i)
{
for (int j = 0; j <= n; ++j)
{
int temp = min(j, n - j);
double t = 0.0;
for (int k = 0; k <= temp; ++k)
{
t = max(t, P*fomer[j+k]+(1-P)*fomer[j-k]);
}
later[j] = t;
}
swap(fomer, later);
}
int i = (LL)X*n / 1000000;
printf("%0.6f\n", fomer[i]);
}
}