HDU--4089(概率DP)

2015-04-21 22:22:23

题意:一队人排着队激活游戏,服务器每次对队首的人的要求进行处理,有4种可能:

  (1)失败,概率p1  (2)失联,排到队末,概率p2  (2)成功,概率p3  (4)服务器崩溃,概率p4

  一开始一队有n个人,某人排在第m个,问服务器崩溃时该人前面的人数 <= k-1 的概率。

思路:

  一开始完全木有思路... TAT,看了博客~

  好一道概率DP,还卡了空间... 必须用滚动数组优化一下。

  首先,dp数组的定义很重要,dp[i][j]表示一队共 i 个人,该人排在第 j 个时到达目标状态的概率。

  列出方程:

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

  2<=j<=k: dp[i][j] = dp[i][j]*p1 + dp[i][j-1]*p2 + dp[i-1][j-1]*p3 + p4;

   k<j<=i: dp[i][j] = dp[i][j]*p1 + dp[i][j-1]*p2 + dp[i-1][j-1]*p3

  令 : P2 = p2/(1-p1) , P3 = p3/(1-p1) , P4 = p4/(1-p1),转化方程为:

  j == 1 : dp[i][1] = dp[i][i]*P2 + P4

  2<=j<=k: dp[i][j] = dp[i][j-1]*P2 + dp[i-1][j-1]*P3 + P4;

   k<j<=i: dp[i][j] = dp[i][j-1]*P2 + dp[i-1][j-1]*P3

  ※我们发现,每层循环首先要求出dp[i][1],我们可以循环迭代一下得到下列方程:

   

  注意:如果p4==0或者p1==1,答案显然0

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=0;i<(n);++i)
17 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
18 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
19 #define MP(a,b) make_pair(a,b)
20 
21 typedef long long ll;
22 typedef pair<int,int> pii;
23 const int INF = (1 << 30) - 1;
24 const int MAXN = 2001;
25 const double eps = 1e-4;
26 
27 int n,m,k;
28 double p1,p2,p3,p4;
29 double P2,P3,P4;
30 double dp[2][MAXN];
31 double pw[MAXN];
32 
33 int main(){
34     while(scanf("%d%d%d%lf%lf%lf%lf",&n,&m,&k,&p1,&p2,&p3,&p4) != EOF){
35         if(fabs(p4) < eps || fabs(p1 - 1.0) < eps){
36             printf("0.00000\n");
37             continue;
38         }
39         P2 = p2 / (1.0 - p1);
40         P3 = p3 / (1.0 - p1);
41         P4 = p4 / (1.0 - p1);
42         pw[0] = 1.0;
43         for(int i = 1; i <= n; ++i) pw[i] = pw[i - 1] * P2;
44         MEM(dp,0);
45         dp[1][1] = P4 / (1.0 - P2);
46          for(int i = 2; i <= n; ++i){
47             int id = i&1;
48             double cur = 0;
49             for(int j = 1; j <= i - 1; ++j) cur += dp[id^1][j] * pw[i - j] * P3;
50             for(int j = max(1,i - k + 1); j <= i - 1; ++j) cur += P4 * pw[j];
51             dp[id][1] = (cur + P4) / (1.0 - pw[i]);
52             for(int j = 2; j <= k; ++j)
53                 dp[id][j] = dp[id][j - 1] * P2 + dp[id^1][j - 1] * P3 + P4;
54             for(int j = k + 1; j <= i; ++j)
55                 dp[id][j] = dp[id][j - 1] * P2 + dp[id^1][j - 1] * P3;
56         }
57         printf("%.5f\n",dp[n&1][m]);
58     }
59     return 0;
60 }

 

posted @ 2015-04-21 22:55  Naturain  阅读(133)  评论(0编辑  收藏  举报