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 }

 

你可能感兴趣的:(poj)