poj3071_概率dp

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

题意:

有2^n次方个队,已知任意两个队之间每个队获胜的概率,比赛的规则相邻的两个队伍之间比赛,赢的继续下一轮,输的直接淘汰(相邻的两个队伍是指,  1,2     3,4    5,6.......也就是说2和3 不比赛。如果1,2中假设1赢了,1再跟3,4中的赢家比赛,这样最后赢的那个队一共打了n场比赛。

我们用dp[ i ][ j ]表示j参加的第i场比赛赢的概率,那么有 递推方程  dp [ i ] [ j ]  =   dp [ i -1  ] [ j ] *dp [ i -1 ] [ k ] *p [ j ] [ k ],j参加的第i场比赛赢,那么 j参加的第i-1场比赛肯定赢,所以有dp[i-][j] ,  第i场比赛j的对手是k,j赢,所以有 p[ j ] [ k ], 那么既然k也能够打到第i场比赛,那说明k打的第i-1场比赛也一定赢,所以有 dp[ i-1 ] [ k ].

问题是k如果表示,自己想想咯

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <vector>
 7 #include <cmath>
 8 #include <queue>
 9 #include <set>
10 #include <map>
11 #define INF 0x3f3f3f3f
12 using namespace std;
13 typedef long long LL;
14 
15 double dp[8][1 << 7], p[1<<7][1<<7];
16 int main()
17 {
18     int n;
19     while(~scanf("%d", &n))
20     {
21         if(n == -1)
22             break;
23         for(int i = 0; i < (1 << n); i++)
24             for(int j = 0; j < (1 << n); j++)
25                 scanf("%lf", &p[i][j]);
26         memset(dp, 0, sizeof(dp));
27         for(int j = 0; j < (1<<n); j++)
28             dp[0][j] = 1;
29         for(int i = 1; i <= n; i++)
30         {
31             for(int j = 0; j < (1 << n); j++)
32             {
33                 int te = j / (1 << (i-1));
34                 te ^= 1;
35                 for(int k = te * (1 << (i-1)); k < te * (1 << (i-1)) + (1 << (i-1)); k++)
36                     dp[i][j] += dp[i - 1][j] * dp[i - 1][k] * p[j][k];
37             }
38         }
39         int res = 0;
40         double mm = 0;
41         for(int i = 0; i < (1 << n); i++)
42         {
43             if(mm < dp[n][i]){
44                 mm = dp[n][i];
45                 res = i + 1;
46             }
47         }
48         printf("%d\n", res);
49     }
50     return 0;
51 }
View Code

 

posted @ 2016-07-25 15:37  海无泪  阅读(288)  评论(0编辑  收藏  举报