題意:
進行一局遊戲,你有 p 的概率獲勝。有一個概率 q 初始爲 2% ,如果你獲勝,你將有 q 的概率獲得獎勵;如果你沒得到獎勵, q 會變化, ;如果你輸了, q 也會變化, 。
問獲得獎勵的期望局數爲多少。
分析:
很明顯的期望 dp 。對於普通的期望 dp ,一般是把結局的概率作爲1,從開始進行記憶化遞歸。但是對於本題。開始時沒有得到獎勵,就是0,得到獎勵就是1,只有 0->1 ,顯然不行。
既然是dp,那就要有多條轉移路徑的狀態,將狀態作爲dp數組的下標。發現本題中 q 是有多條轉化的路徑的,我們不妨將 q 作爲狀態。但是作爲數組下標一定要是整數,那就,即100%對應 ,25.5%對應 。
表示當 時,得到獎勵的期望。
期望=概率*局數
//這一局沒贏,以後獲得了獎勵;
//這一局贏了,且獲得了獎勵;
//這一局贏了,但沒獲得獎勵,以後獲得了獎勵,別忘了*(1-q),代表沒獲得獎勵
注意轉移的時候要加1,即當前沒贏的這一局。本局直接獲得獎勵的話,所需局數是1;否則就是下一個狀態的局數+1.
我們把上下兩項的“1”提出來,與p*q組合
綜上所述,
那麼開始時狀態就是 , 結束時狀態就是 。
即使,但是可能這局輸了,根本就沒機會的獎勵
因爲直接寫的等於1,檢查了好久
證明其實就是很簡單,如果這一把輸了,下一把的q仍爲100%。
設
E=(1-p)*E+1+p*(1-1)*E
化簡可得
至此,答案顯然易見。
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int N=1e3+5;
const double eps=1e-6;
typedef long double ld;
ld dp[N];
ld p;
void dfs(int rate)
{
ld q=(double)rate/1000.0;
int nxt1=min(rate+15,1000),nxt2=min(rate+20,1000);
if(nxt1<1000&&fabs(dp[nxt1])<eps) dfs(nxt1);
if(nxt2<1000&&fabs(dp[nxt2])<eps) dfs(nxt2);
dp[rate]=(1-p)*dp[nxt1]+1+p*(1-q)*dp[nxt2];
}
int main()
{
int t;
cin>>t;
for(int it=1;it<=t;it++)
{
cin>>p;
memset(dp,0,sizeof(dp));
p/=100;
dp[1000]=1.00/p;
dfs(20);
cout<<"Case "<<it<<": "<<fixed<<setprecision(10)<<dp[20]<<endl;
}
}