Activation
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4089
题意:
有个人在排队注册游戏账号,这整个队列共有N个人并且他目前位于第M个位置,因为官网的服务器不大好,所以随时有可能会崩溃,在此之前每个位于队列第一个位置的人都会面临四个随机事件:
1、注册失败,队列保持不变 概率为p1
2、注册失败,走到队列尾部 概率为p2
3、注册成功,离开队列 概率为p3
4、服务器崩溃了 概率为p4
求在服务器奔溃的时候此人在队列中的位置大于等于k的概率
题解:
设dp[i][j]为当队列中人数为i且此人位于第j位时达到目标状态的概率,则dp[n][m]即所求答案
则可以推出
dp[i][j]=p1*dp[i][j]+p2*dp[i][i]+p4 j==1
dp[i][j]=p1*dp[i][j]+p2*dp[i][j-1]+p3*dp[i-1][j-1]+p4 1<j<=k
dp[i][j]=p1*dp[i][j]+p2*dp[i][j-1]+p3*dp[i-1][j-1] k<j<=i
设p=p2/(1-p1)则可化简得
dp[i][j]=p*dp[i][i]+p4/(1-p1) j==1
dp[i][j]=p*dp[i][j-1]+(p3*dp[i-1][j-1]+p4)/(1-p1) 1<j<=k
dp[i][j]=p*dp[i][j-1]+(p3*dp[i-1][j-1])/(1-p1) k<j<=i
迭代可得dp[i][i],再依次递推即可,求解过程中注意分母为0的情况
代码
#include<stdio.h>
#include<math.h>
double dp[2001][2001],c[2001];
int main()
{
int n,m,k;
double p,p1,p2,p3,p4,km,f;
while(~scanf("%d%d%d%lf%lf%lf%lf",&n,&m,&k,&p1,&p2,&p3,&p4))
{
if(fabs(1.0-p1-p2)<1e-9)
{
puts("0.00000");
continue;
}
p=p2/(1-p1),c[0]=1.0;
for(int i=1;i<=n;++i)
c[i]=c[i-1]*p;
for(int i=1;i<=n;++i)
{
km=p4/(1-p1)*c[i-1];
for(int j=1;j<=i;++j)
{
if(1<j&&j<=k)f=(p3*dp[i-1][j-1]+p4)/(1-p1);
else f=(p3*dp[i-1][j-1])/(1-p1);
km+=f*c[i-j];
}
dp[i][i]=km/(1-c[i]);
for(int j=1;j<i;++j)
if(j==1)dp[i][j]=(p2*dp[i][i]+p4)/(1.0-p1);
else if(1<j&&j<=k)dp[i][j]=(p2*dp[i][j-1]+p3*dp[i-1][j-1]+p4)/(1.0-p1);
else dp[i][j]=(p2*dp[i][j-1]+p3*dp[i-1][j-1])/(1.0-p1);
}
printf("%.5f
",dp[n][m]);
}
}