Activation HDU - 4089 概率期望dp

题意:
n个人排队激活,对于队列中的第一个人,在激活的时候有以下五种情况:
1.激活失败:留在队列中继续等待下一次激活(概率p1)
2.失去连接:激活失败,并且出队列然后排到队列的尾部(概率p2)
3.激活成功:出队列(概率p3)
4.服务器瘫:服务器停止服务了,所有人都无法激活了(概率p4)
求服务器瘫痪并且此时Tomato在队伍的位置在<=k的概率,也就是前面最多有k-1个人

分析:
dp[i][j]:队伍一共有i个人,排在第j位置,达到目标的概率

当j==1时,dp[i][1]=dp[i][1]*p1+dp[i][i]*p2+dp[i][0]*p3+p4;dp[i][0]=0;
当1 < j<=k时,dp[i][j]=dp[i][j]*p1+dp[i][j-1]*p2+dp[i-1][j-1]*p3+p4
当j> k时,dp[i][j]=dp[i][j]*p1+dp[i][j-1]*p2+dp[i-1][j-1]*p3;

然后化简一下使
p21=p2/(1-p1);
p31=p3/(1-p1);
p41=p4/(1-p1);
当j==1时,dp[i][1]=dp[i][i]*p21+p41
当1 < j<=k时,dp[i][j]=dp[i][j-1]*p21+dp[i-1][j-1]*p31+p41
当j> k时,dp[i][j]=dp[i][j-1]*p21+dp[i-1][j-1]*p31;

为了简单点,可以用c[j]来表示之前求出来的值,比如c[1]=p41,当1 < j<=k时,c[j]=dp[i-1][j-1]*p31+p41,当j> k时,c[j]=dp[i-1][j-1]*p31;
然后递推就行了。然后发现在求dp[i][1]的时候要用到dp[i][i],成环了,高斯?
这里不用,可以直接迭代,求出dp[i][i]。

关于特判问题/如果不加的话会wa,或者T。
有可能计算过程中分母非常接近0,于是计算结果出现NaN,代码继续用NaN参与计算就会变得非常慢。
所以,一定注意每一步会不会出现分母为0 的情况,以及预处理的时候对于一些特殊情况导致自己的式子会出现分母为0的情况

using namespace std;
double p1,p2,p3,p4,p21,p31,p41;
double dp[2005][2005],c[2005];
int n,m,k;
int main(){
    while(scanf("%d%d%d%lf%lf%lf%lf",&n,&m,&k,&p1,&p2,&p3,&p4)!=EOF){
        if(abs(1-p1-p2)<1e-5){printf("0.00000\n");continue;}
        p21=p2/(1-p1);
        p31=p3/(1-p1);
        p41=p4/(1-p1);
        dp[1][1]=p41/(1-p21);
        for(int i=2;i<=n;i++)
        {
            int t=k;if(i<k) t=i;
            c[1]=p41;
            for(int j=2;j<=t;j++)
                c[j]=dp[i-1][j-1]*p31+p41;
            for(int j=k+1;j<=i;j++)
                c[j]=dp[i-1][j-1]*p31;
            double tmp=0,p=1;
            for(int j=i;j>=1;j--)
            {
                tmp+=c[j]*p;
                p=p*p21;
            }
            dp[i][i]=(tmp)/(1-p);
            dp[i][1]=dp[i][i]*p21+c[1];
            for(int j=2;j<i;j++)
                dp[i][j]=dp[i][j-1]*p21+c[j];
        }
        printf("%.5f\n",dp[n][m]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值