状态: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; }