hdu 4089 Activation 概率DP

状态:dp[i][j] ,队列中有i个人,当前的位置是j。

dp[i][1] = p21*dp[i][i] + p41

if(j <= k) dp[i][j] =p31* dp[i -1][j-1] + p21 *dp[i][j-1] + p41;

if(j > k) dp[i][j] = p31* dp[i -1][j-1] + p21 *dp[i][j-1] ;

dp[i-1][j-1]是已知的,dp[i][j-1]是一个带有dp[i][i] 的方程

所以到最后dp[i][i]可以被先求出来。

概率题可以可以有两种递推方式,可以从结果到起点,也可以从起点到结果,这里用了第一种,基本原理还是用了条件概率。

#include<cstdio>
#include<cstring>
#define eps 1e-8
#define abs(x) ((x)>0?(x):-(x))
#define zero(x) (abs(x)<eps)
const int LMT=2003;
double p[5],dp[LMT][LMT];
double x[LMT],z[LMT];
int main(void)
{
    double p21,p31,p41;
    int n,m,k,i,j;
    while(~scanf("%d%d%d%lf%lf%lf%lf",&n,&m,&k,&p[1],&p[2],&p[3],&p[4]))
    {
        if(zero(p[4]))
        {
            printf("0.00000\n");
            continue;
        }
        p21=p[2]/(1-p[1]);
        p31=p[3]/(1-p[1]);
        p41=p[4]/(1-p[1]);
        dp[1][1]=p[4]/(1-p[2]-p[1]);
        for(i=2;i<=n;++i)
        {
            x[1]=p21;z[1]=p41;
            for(j=2;j<=i;++j)
            {
                x[j]=x[j-1]*p21;
                z[j]=p31*dp[i-1][j-1]+p21*z[j-1];
                if(j<=k)z[j]+=p41;
            }
              dp[i][i]=z[i]/(1-x[i]);
            for(j=1;j<i;++j)
                  dp[i][j]=x[j]*dp[i][i]+z[j];
        }
        printf("%.5lf\n",dp[n][m]);
    }
    return 0;
}


你可能感兴趣的:(hdu 4089 Activation 概率DP)