hdu4870(概率dp)

多校賽1010

題意:一場比賽,贏了可以得50分,輸了扣100分,始終用分數低的號比賽。此時把50看成一個單位,已知贏一場比賽的概率爲p求打到20分的場數的期望值。

鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4870點擊打開鏈接

思路:我們用dp[i]表示i到20的期望步數,則狀態轉移方程如下:

q=1-p;

dp[0]=dp[1]*p+dp[0]*q+1;

dp[1]=dp[2]*p+dp[0]*q+1;

dp[2]=dp[3]*p+dp[0]*q+1;

…………

dp[i]=dp[i+1]*p+dp[i-2]*q+1;   ---------------1

dp[i+1]=dp[i+2]*p+dp[i-1]*q+1;--------------2

dp[19]=dp[20]*p+dp[17]*q+1;

dp[20]=0;

我們用2式減去1式得到dp[i+1]-dp[i]=(dp[i+2]-dp[i+1])*p+(dp[i-1]-dp[i-2])*q;-------------3

其中dp[i+1]-dp[i]就是步數從i到i+1的期望,令dp[i+1]-dp[i]=t[i],則3式可變成下式

t[i]=t[i+1]*p+t[i-2]*q;

移項得到t[i+1]=(t[i]-t[i-2]*q)/p;這樣的話就可以根據前面得到的結果遞推了。(注意初始化問題)

由於有兩個賬號,統計結果的時候每次加2*t[i];到最後一項的時候只需要加t[i],就可以滿足要求了!代碼如下:



#include<set>
#include<cstdio>
#include<iostream>
using namespace std;
double t[22];
int main()
{
    double p;
    while(scanf("%lf",&p)!=EOF)
    {
        double q=1-p;
        t[0]=1/p;
        t[1]=t[0]/p;
        t[2]=t[1]/p;
        for(int i=3;i<=19;i++)
            t[i]=(t[i-1]-t[i-3]*q)/p;
        double res=0;
        for(int i=0;i<19;i++)res+=2*t[i];
        printf("%.6lf\n",res+t[19]);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章