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; }