TopCoder SRM 339 Div1 Medium TestBettingStrategy
問題
nドルを賭け、勝つとnドルがもらえ、負けるとそのnドルを失うギャンブルがある。
次のような方針で賭けをする。
- 最初は1ドルを賭ける
- 負けた場合、前のラウンドの倍のお金を賭ける
- 勝った場合、前のラウンドの掛け金にかかわらず1ドルをかける
最初initSumドルのお金を持っていて、roundsラウンド回(途中でやめてもよい)賭けをする。
一回のラウンドで勝つ確率がprob%のとき、お金をgoalSum以上に出来る確率を求めよ。
制約条件
initSum,goalSum≦1000
1≦rounds≦50
0≦prob≦100
方針
動的計画法による。
dp[i][j][k]を、iラウンド目まで賭けをして、現在の持ち金がjであり、今までにk回連続で負けているような確率とする。
kから次のラウンドの掛け金がわかるので、テーブルを更新していくようなDPができる。
ソースコード
double dp[2][12][1001]; class TestBettingStrategy { public: double winProbability(int initSum, int goalSum, int rounds, int prob) { memset(dp[0],0,sizeof(dp[0])); dp[0][0][initSum]=1; int cur=0, next=1; rep(i,rounds){ memset(dp[next],0,sizeof(dp[next])); rep(j,1001)rep(k,11)if(dp[cur][k][j]){ if(j>=goalSum||j<(1<<k))dp[next][k][j]+=dp[cur][k][j]; else{ dp[next][0][min(1000,j+(1<<k))]+=dp[cur][k][j]*prob/100; dp[next][k+1][j-(1<<k)]+=dp[cur][k][j]*(1-prob/100.0); } } swap(cur,next); } double ans=0; for(int i=goalSum;i<=1000;i++)rep(j,12)ans+=dp[cur][j][i]; return ans; } };