HDU 6558 The Moon

題意:
進行一局遊戲,你有 p 的概率獲勝。有一個概率 q 初始爲 2% ,如果你獲勝,你將有 q 的概率獲得獎勵;如果你沒得到獎勵, q 會變化, q=min(100%,q+2%)q=min(100\%,q+2\%);如果你輸了, q 也會變化, q=min(100%,q+1.5%)q=min(100\%,q+1.5\%)
問獲得獎勵的期望局數爲多少。

分析:
很明顯的期望 dp 。對於普通的期望 dp ,一般是把結局的概率作爲1,從開始進行記憶化遞歸。但是對於本題。開始時沒有得到獎勵,就是0,得到獎勵就是1,只有 0->1 ,顯然不行。
既然是dp,那就要有多條轉移路徑的狀態,將狀態作爲dp數組的下標。發現本題中 q 是有多條轉化的路徑的,我們不妨將 q 作爲狀態。但是作爲數組下標一定要是整數,那就10*10,即100%對應 dp[1000]dp[1000] ,25.5%對應 dp[255]dp[255]
dp[i]dp[i] 表示當 q=i/1000q=i/1000 時,得到獎勵的期望。

期望=概率*局數

dp[i]=(1p)(dp[min(i+15,1000)]+1)dp[i]=(1-p)*(dp[min(i+15,1000)]+1) //這一局沒贏,以後獲得了獎勵;

+pq1+p*q*1 //這一局贏了,且獲得了獎勵;

+p(1q)(dp[min(i+20,1000)]+1)+p*(1-q)*(dp[min(i+20,1000)]+1)//這一局贏了,但沒獲得獎勵,以後獲得了獎勵,別忘了*(1-q),代表沒獲得獎勵

注意轉移的時候要加1,即當前沒贏的這一局。本局直接獲得獎勵的話,所需局數是1;否則就是下一個狀態的局數+1.

我們把上下兩項的“1”提出來,與p*q組合

(1p)+pq+p(1q)=1(1-p)+p*q+p*(1-q)=1

綜上所述,dp[i]=(1p)dp[min(i+15,1000)]+1+p(1q)dp[min(i+20,1000)]dp[i]=(1-p)*dp[min(i+15,1000)]+1+p*(1-q)*dp[min(i+20,1000)]

那麼開始時狀態就是 dp[20]dp[20] , 結束時狀態就是 dp[1000]dp[1000]

dp[1000]1,dp[1000]=1pdp[1000]\neq1,dp[1000]=\frac{1}{p}即使q=100%q=100\%,但是可能這局輸了,根本就沒機會的獎勵

因爲直接寫的等於1,檢查了好久

證明其實就是很簡單,如果這一把輸了,下一把的q仍爲100%。

dp[1000]=Edp[1000]= E

E=(1-p)*E+1+p*(1-1)*E

化簡可得 E=1pE=\frac{1}{p}

至此,答案顯然易見。

#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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章