状态:dp[i][j] ,队列中有i个人,当前的位置是j。
dp[i][1] = p21*dp[i][i] + p41
if(j <= k) dp[i][j] =p31* dp[i -1][j-1] + p21 *dp[i][j-1] + p41;
if(j > k) dp[i][j] = p31* dp[i -1][j-1] + p21 *dp[i][j-1] ;
dp[i-1][j-1]是已知的,dp[i][j-1]是一个带有dp[i][i] 的方程
所以到最后dp[i][i]可以被先求出来。
概率题可以可以有两种递推方式,可以从结果到起点,也可以从起点到结果,这里用了第一种,基本原理还是用了条件概率。
#include<cstdio>
#include<cstring>
#define eps 1e-8
#define abs(x) ((x)>0?(x):-(x))
#define zero(x) (abs(x)<eps)
const int LMT=2003;
double p[5],dp[LMT][LMT];
double x[LMT],z[LMT];
int main(void)
{
double p21,p31,p41;
int n,m,k,i,j;
while(~scanf("%d%d%d%lf%lf%lf%lf",&n,&m,&k,&p[1],&p[2],&p[3],&p[4]))
{
if(zero(p[4]))
{
printf("0.00000\n");
continue;
}
p21=p[2]/(1-p[1]);
p31=p[3]/(1-p[1]);
p41=p[4]/(1-p[1]);
dp[1][1]=p[4]/(1-p[2]-p[1]);
for(i=2;i<=n;++i)
{
x[1]=p21;z[1]=p41;
for(j=2;j<=i;++j)
{
x[j]=x[j-1]*p21;
z[j]=p31*dp[i-1][j-1]+p21*z[j-1];
if(j<=k)z[j]+=p41;
}
dp[i][i]=z[i]/(1-x[i]);
for(j=1;j<i;++j)
dp[i][j]=x[j]*dp[i][i]+z[j];
}
printf("%.5lf\n",dp[n][m]);
}
return 0;
}