poj 3071 概率dp

转自:cxlove

题目:有2^n个队,相邻的两两打淘汰赛,,求最后哪个队夺冠的概率最大

dp[i][j]表示第i轮的时候,第j去支队伍赢的概率。

那么dp[i][j]的前提就是i-1轮的时候,j是赢的,而且第i轮赢了对方

接下来就是找到第i轮的时候,他的可能队手

通过二进制可以发现规律,所有高位是一样的,第i位刚好相反,所以用位运算可以巧妙解决,见代码

dp[i][j]=sigma(dp[i-1][j]*dp[i-1][k]*p[j][k])

 1 #include<stdio.h>

 2 #include<iostream>

 3 #include<algorithm>

 4 #include<string.h>

 5 using namespace std;

 6 double dp[8][200];//dp[i][j]表示在第i场比赛中j胜出的概率

 7 double p[200][200];

 8 int main()

 9 {

10     int n;

11     #ifndef ONLINE_JUDGE

12     freopen("1.in","r",stdin);

13     #endif

14     while(scanf("%d",&n)!=EOF)

15     {

16         if(n==-1)break;

17         memset(dp,0,sizeof(dp));

18         for(int i=0;i<(1<<n);i++)

19           for(int j=0;j<(1<<n);j++)

20             scanf("%lf",&p[i][j]);

21         for(int i=0;i<(1<<n);i++) dp[0][i]=1;

22         for(int i=1;i<=n;i++){

23             for(int j=0;j<(1<<n);j++){

24                 for(int k=0;k<(1<<n);k++){

25                     if(((j>>(i-1))^1)==(k>>(i-1)))

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

27                 }

28             }

29         }

30         int ans;

31         double temp=0;

32         for(int i=0;i<(1<<n);i++)

33         {

34             if(dp[n][i]>temp)

35             {

36                 ans=i;

37                 temp=dp[n][i];

38             }

39         }

40         printf("%d\n",ans+1);

41     }

42     return 0;

43 }

 

你可能感兴趣的:(poj)