[HDU 4089] Activation

一堆人排队,初始队列为1,2...n,男主在第m个

有四个操作

  1.保持原序列不变

  2.队首到队尾,其余依此前移

  3.队首狗带

  4.整个队伍炸了

概率分别为p1,p2,p3,p4
求爆炸时男主在队伍前K位的概率的期望

dp[i][j]表示当前队伍有i人,男主排在j的答案的期望

dp[i][1]=dp[i][1]*p1+dp[i][i]*p2+p4

dp[i][j]=dp[i][j]*p1+dp[i][j-1]*p2+dp[i-1][j-1]*p3+p4*(j<=k)

移项,并对p2,p3,p4均除以(1-p1)得

dp[i][1]=dp[i][i]*p2+p4
dp[i][j]=dp[i][j-1]*p2+dp[i-1][j-1]*p3+p4*(j<=k)

因为dp[i][1]需要通过dp[i][i]计算

所以我们通过迭代得到形似dp[i][i]=A*dp[i][i]+B的式子,解出dp[i][i]

然后依此算就好啦www

tips:要用滚动数组,不然炸空间,p4=0根本停不下来~~~

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define eps 1e-5
 4 #define maxn 2005
 5 int N,M,K;
 6 double p1,p2,p3,p4,dp[2][maxn];
 7 bool eq(double x,double y){ return fabs(x-y)<eps; }
 8 int main(){
 9     while(scanf("%d%d",&N,&M)!=EOF){
10         memset(dp,0,sizeof(dp));
11         double *cur=dp[0],*lst=dp[1];
12         scanf("%d",&K);
13         scanf("%lf%lf%lf%lf",&p1,&p2,&p3,&p4);
14         if(eq(p4,0))printf("%.5lf
",0.0);
15         else{
16             p2/=(1-p1),p3/=(1-p1),p4/=(1-p1);
17             for(int i=1;i<=N;i++){
18                 double xi=p2,cng=p4;
19                 for(int j=2;j<=i;j++)
20                     xi*=p2,cng=cng*p2+lst[j-1]*p3+p4*(j<=K);
21                 cur[1]=cng/(1-xi)*p2+p4;
22                 for(int j=2;j<=i;j++)
23                     cur[j]=cur[j-1]*p2+lst[j-1]*p3+p4*(j<=K);
24                 swap(lst,cur);
25             }
26             printf("%.5f
",lst[M]);
27         }
28     }
29     return 0;
30 }
View Code
原文地址:https://www.cnblogs.com/Ngshily/p/5520164.html