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 }

 

posted @ 2015-04-11 10:23  miao_a_miao  阅读(117)  评论(0编辑  收藏  举报