11年北京现场赛的题目。概率DP。
公式化简起来比较困难。。。。而且就算结果做出来了,没有考虑特殊情况照样会WA到死的。。。。
去参加区域赛一定要考虑到各种情况。
像概率dp,公式推出来就很容易写出来了。
1 /* 2 HDU 4098 3 题意:有n个人排队等着在官网上激活游戏。Tomato排在第m个。 4 对于队列中的第一个人。有一下情况: 5 1、激活失败,留在队列中等待下一次激活(概率为p1) 6 2、失去连接,出队列,然后排在队列的最后(概率为p2) 7 3、激活成功,离开队列(概率为p3) 8 4、服务器瘫痪,服务器停止激活,所有人都无法激活了。 9 求服务器瘫痪时Tomato在队列中的位置<=k的概率 10 11 解析: 12 概率DP; 13 设dp[i][j]表示i个人排队,Tomato排在第j个位置,达到目标状态的概率(j<=i) 14 dp[n][m]就是所求 15 j==1: dp[i][1]=p1*dp[i][1]+p2*dp[i][i]+p4; 16 2<=j<=k: dp[i][j]=p1*dp[i][j]+p2*dp[i][j-1]+p3*dp[i-1][j-1]+p4; 17 k<j<=i: dp[i][j]=p1*dp[i][j]+p2*dp[i][j-1]+p3*dp[i-1][j-1]; 18 化简: 19 j==1: dp[i][1]=p*dp[i][i]+p41; 20 2<=j<=k: dp[i][j]=p*dp[i][j-1]+p31*dp[i-1][j-1]+p41; 21 k<j<=i: dp[i][j]=p*dp[i][j-1]+p31*dp[i-1][j-1]; 22 23 其中: 24 p=p2/(1-p1); 25 p31=p3/(1-p1) 26 p41=p4/(1-p1) 27 28 可以循环i=1->n 递推求解dp[i].在求解dp[i]的时候dp[i-1]就相当于常数了。 29 在求解dp[i][1~i]时等到下列i个方程 30 j==1: dp[i][1]=p*dp[i][i]+c[1]; 31 2<=j<=k:dp[i][j]=p*dp[i][j-1]+c[j]; 32 k<j=i: dp[i][j]=p*dp[i][j]+c[j]; 33 其中c[j]都是常数了。上述方程可以解出dp[i]了。 34 首先是迭代得到 dp[i][i].然后再代入就可以得到所有的dp[i]了。 35 36 注意特判一种情况。就是p4<eps时候,就不会崩溃了,应该直接输出0 37 */ 38 #include<stdio.h> 39 #include<iostream> 40 #include<math.h> 41 #include<algorithm> 42 #include<string.h> 43 using namespace std; 44 45 const int MAXN=2020; 46 const double eps=1e-5; 47 double c[MAXN]; 48 double pp[MAXN]; 49 double dp[MAXN][MAXN]; 50 int main() 51 { 52 int n,m,k; 53 double p1,p2,p3,p4; 54 while(scanf("%d%d%d%lf%lf%lf%lf",&n,&m,&k,&p1,&p2,&p3,&p4)!=EOF) 55 { 56 if(p4<eps) 57 { 58 printf("0.00000 "); 59 continue; 60 } 61 double p=p2/(1-p1); 62 double p41=p4/(1-p1); 63 double p31=p3/(1-p1); 64 pp[0]=1.0;//pp[i]=p^1; 65 for(int i=1;i<=n;i++) pp[i]=p*pp[i-1]; 66 67 dp[1][1]=p41/(1-p); 68 c[1]=p41; 69 for(int i=2;i<=n;i++) 70 { 71 for(int j=2;j<=k;j++)c[j]=p31*dp[i-1][j-1]+p41; 72 for(int j=k+1;j<=i;j++) c[j]=p31*dp[i-1][j-1]; 73 double tmp=c[1]*pp[i-1]; 74 for(int j=2;j<=k;j++)tmp+=c[j]*pp[i-j]; 75 for(int j=k+1;j<=i;j++)tmp+=c[j]*pp[i-j]; 76 dp[i][i]=tmp/(1-pp[i]); 77 dp[i][1]=p*dp[i][i]+c[1]; 78 for(int j=2;j<i;j++)dp[i][j]=p*dp[i][j-1]+c[j]; 79 } 80 printf("%.5lf ",dp[n][m]); 81 } 82 return 0; 83 }