poj 3071 简单概率dp

题意很清晰,就是问最有可能获得冠军的队伍。

需要注意的是每轮比赛中,每个队都是和自己旁边的一个队比赛,采用淘汰赛制,所以需要决定第i轮的时候j队可以和哪些队比赛,然后求概率dp即可。

状态转移方程:

  dp[i][j] += dp[i - 1][j] * dp[i - 1][k] * p[j][k];

  dp[i][j]表示第i轮j队获胜的概率 = 第i-1轮j队获胜的概率 * 第i-1轮k队获胜的概率 * j队打败k队的概率(之和)。

  前提是j和k在第i轮可能遇到。

  判断方法: ( j >> ( i - 1 ) ) ^ 1 == k >> ( i - 1 ) 

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 
 6 const int N = 8;
 7 const int M = 1 << 7;
 8 double dp[N][M];
 9 double p[M][M];
10 
11 int main ()
12 {
13     int n, m;
14     while ( scanf("%d", &n) != EOF )
15     {
16         if ( n == -1 ) break;
17         m = 1 << n;
18         for ( int i = 0; i < m; i++ )
19         {
20             for ( int j = 0; j < m; j++ )
21             {
22                 scanf("%lf", &p[i][j]);
23             }
24         }
25         for ( int j = 0; j < m; j++ )
26         {
27             dp[0][j] = 1.0;
28         }
29         for ( int i = 1; i <= n; i++ )
30         {
31             for ( int j = 0; j < m; j++ )
32             {
33                 dp[i][j] = 0;
34                 for ( int k = 0; k < m; k++ )
35                 {
36                     if ( ( ( j >> ( i - 1 ) ) ^ 1 ) == ( k >> ( i - 1 ) ) )
37                     {
38                         dp[i][j] += dp[i - 1][j] * dp[i - 1][k] * p[j][k];
39                     }
40                 }
41             }
42         }
43         int ans = 0;
44         for ( int j = 1; j < m; j++ )
45         {
46             if ( dp[n][j] > dp[n][ans] )
47             {
48                 ans = j;
49             }
50         }
51         printf("%d
", ans + 1);
52     }
53     return 0;
54 }
原文地址:https://www.cnblogs.com/huoxiayu/p/4658304.html