欢迎访问我的个人网站==》 jiashubing.cn

HDU 4089 Activation(概率DP)(转)

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\n");
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\n",dp[n][m]);
81     }
82     return 0;
83 }

 

posted @ 2013-07-29 23:56  贾树丙  阅读(339)  评论(0编辑  收藏  举报