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
",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
",p[n&1][m]);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/xuesu/p/4496209.html