HDU 4089 Activation 概率DP 难度:3

http://acm.hdu.edu.cn/showproblem.php?pid=4089

这道题中一共有两个循环:

1.事件1 如果一直落在Activation failed事件上,那么就会重新继续直到出现事件2,3,或4为止,

这样 进入事件2的概率是p2'=p2+p2*p1+p2*p1*p1........解这个无穷级数得到p2'=p2/(1-p1),同理,p3'=p3/(1-p1),p4=p4/(1-p1)

2.事件2

设dp[i][j]为队列长度为i,主角在j时满足条件的概率,则

当j==1:

dp[i][1]=dp[i][i]*p2'+p4'

1<=j<=k:

dp[i][j]=dp[i][j-1]*p2'+dp[i-1][j-1]*p3'+p4'

j>=k:

dp[i][j]=dp[i][j-1]*p2'+dp[i-1][j-1]*p3'

很明显,所有dp[i][j]都可以由dp[i][i]表示,且dp[i][i]的系数为p2'^j,常数项则为
            c[j]=p3*p[cnt^1][j-1]+c[j-1]*p2+p4 if j<=k then 0;

那么首先解出c[i],然后即可得到dp[i][i],然后代回得到dp[i][j]即可

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

#include <queue>

using namespace std;

const int maxn=2e3+1;

const double eps=1e-9;

int n,m,k;

double p1,p2,p3,p4;

double tp2[maxn];

double p[2][maxn],c[maxn];

void calc(){

    //memset(p,0,sizeof(p));

    p[1][1]=p4/(1-p2);

    int cnt=0;

    for(int i=2;i<=n;i++){

        for(int j=1;j<=k;j++){

            c[j]=p3*p[cnt^1][j-1]+c[j-1]*p2+p4;

        }

        for(int j=k+1;j<=i;j++){

            c[j]=p3*p[cnt^1][j-1]+c[j-1]*p2;

        }

        p[cnt][i]=c[i]/(1-tp2[i]);

        for(int j=1;j<i;j++){

            p[cnt][j]=tp2[j]*p[cnt][i]+c[j];

        }

        cnt^=1;

    }

}



int dcmp(double a,double b){

    if(fabs(a-b)<=eps)return 0;

    return a>b?1:-1;

}

int main(){

    while(scanf("%d%d%d",&n,&m,&k)==3){

        scanf("%lf%lf%lf%lf",&p1,&p2,&p3,&p4);

        if(dcmp(p1,1)==0||p4<=1e-4){

            printf("%.5f\n",0.0);

            continue;

        }

        else {

            p2/=(1-p1);

            p3/=(1-p1);

            p4/=(1-p1);

        }

        tp2[0]=1;

        for(int i=1;i<=n;i++){

            tp2[i]=tp2[i-1]*p2;

        }

        calc();

        printf("%.5f\n",p[n&1][m]);

    }

    return 0;

}
View Code

 

你可能感兴趣的:(HDU)