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+;
const double eps=1e-;
int n,m,k;
double p1,p2,p3,p4;
double tp2[maxn];
double p[][maxn],c[maxn];
void calc(){
//memset(p,0,sizeof(p));
p[][]=p4/(-p2);
int cnt=;
for(int i=;i<=n;i++){
for(int j=;j<=k;j++){
c[j]=p3*p[cnt^][j-]+c[j-]*p2+p4;
}
for(int j=k+;j<=i;j++){
c[j]=p3*p[cnt^][j-]+c[j-]*p2;
}
p[cnt][i]=c[i]/(-tp2[i]);
for(int j=;j<i;j++){
p[cnt][j]=tp2[j]*p[cnt][i]+c[j];
}
cnt^=;
}
} int dcmp(double a,double b){
if(fabs(a-b)<=eps)return ;
return a>b?:-;
}
int main(){
while(scanf("%d%d%d",&n,&m,&k)==){
scanf("%lf%lf%lf%lf",&p1,&p2,&p3,&p4);
if(dcmp(p1,)==||p4<=1e-){
printf("%.5f\n",0.0);
continue;
}
else {
p2/=(-p1);
p3/=(-p1);
p4/=(-p1);
}
tp2[]=;
for(int i=;i<=n;i++){
tp2[i]=tp2[i-]*p2;
}
calc();
printf("%.5f\n",p[n&][m]);
}
return ;
}