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