[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\n",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\n",lst[M]); 27 } 28 } 29 return 0; 30 }