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\n", ans + 1); 52 } 53 return 0; 54 }