poj2151_概率dp

题目链接:http://poj.org/problem?id=2151

题意:

ACM比赛中,共M道题,T个队,pij表示第i队解出第j题的概率 

问 每队至少解出一题且冠军队至少解出N道题的概率

分析:
对于需要求得概率比较容易想到:
假设p1为每个队至少解出一题的概率,这个容易算出。
假设p2为每个队至少解出一题但是不超过n-1题的概率
所以最终答案为:p1-p2
现在问题是如何求出p2?
假设dp[i][j]表示第i个队解出的题目<=j的概率
则dp[i][j]=解出1题+解出2题+...解出j题的概率
现在问题转化为如何求解出1,2,3...k题的概率
假设x[i][j][k]表示第i个队在前j题解出k题的概率
则:
x[i][j][k]=x[i][j-1][k-1]*p[i][j]+x[i][j-1][k]*(1-p[i][j]);
所以x[i][M][k]表示的就是第i个队解出k题的概率

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <cstdlib>
 6 #include <cmath>
 7 #include <set>
 8 #include <map>
 9 #include <queue>
10 #include <vector>
11 #define INF 0x3f3f3f3f
12 using namespace std;
13 
14 double an[1010][35], dp[1010][35], sn[1010][35][35];
15 int main()
16 {
17     int n, t, m;
18     while(~scanf("%d %d %d", &m, &t, &n) && n + t + m)
19     {
20         memset(sn, 0, sizeof(sn));
21         memset(dp, 0, sizeof(dp));
22         double res2 = 1;
23         for(int i = 1; i <= t; i++)
24         {
25             double temp = 1;
26             for(int j = 1; j <= m; j++)
27             {
28                 scanf("%lf", &an[i][j]);
29                 temp *= (1 - an[i][j]);
30             }
31             res2 *= (1 - temp);
32         }
33         for(int i = 1; i <= t; i++)
34         {
35             sn[i][0][0] = 1;
36         }
37         for(int i = 1; i <= t; i++)
38         {
39             for(int j = 1; j <= m; j++)
40             {
41                 for(int k = 0; k <= n; k++)
42                 {
43                     if(k == 0)
44                         sn[i][j][k] = (1 - an[i][j]) * sn[i][j - 1][k];
45                     else
46                     {
47                         sn[i][j][k] = sn[i][j - 1][k - 1] * an[i][j] + sn[i][j - 1][k] * (1 - an[i][j]);
48                     }
49                 }
50             }
51         }
52         for(int i = 1; i <= t; i++)
53         {
54             for(int j = 1; j < n; j++){
55                 dp[i][n] += sn[i][m][j];
56             }
57         }
58         double res = 1;
59         for(int i = 1; i <= t; i++)
60             res *= dp[i][n];
61         printf("%.3lf\n", res2 - res);
62     }
63     return 0;
64 }

 

posted @ 2016-07-23 17:54  海无泪  阅读(149)  评论(1编辑  收藏  举报