题意:2^n支球队按照竞赛图踢足球,给你任意两支球队相互之间踢赢的概率,求最后那支球队最可能夺冠。

题解:dp[j][i]代表第j支球队通过第i场比赛的概率,然后dp[j][i]=sum(dp[j][i-1]*dp[j+k][i-1]*p[j][j+k]),k是它这一场可能面对的对手,实际上就是它上一场比赛的第一支队伍+2^(i-1)一直到+2^i。

View Code
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 double p[(1<<7)+3][(1<<7)+3];
 6 double dp[(1<<7)+3][10];
 7 int main()
 8 {
 9     int n;
10     while(scanf("%d",&n)&&n!=-1)
11     {
12         int num=1<<n;
13         memset(dp,0,sizeof(dp));
14         for(int i=1; i<=num; dp[i][0]=1.0,i++)
15             for(int j=1; j<=num; j++)
16                 scanf("%lf",&p[i][j]);
17         for(int i=1; i<=n; i++)
18         {
19             int ce=1<<(i-1),ne=1<<i;
20             for(int j=1; j<=num; j+=ne)
21             {
22                 for(int t=0; t<ce; t++)
23                 {
24                     for(int k=ce; k<ne; k++)
25                     {
26                         dp[j+t][i]+=dp[j+t][i-1]*dp[j+k][i-1]*p[j+t][j+k];
27                         dp[j+k][i]+=dp[j+t][i-1]*dp[j+k][i-1]*p[j+k][j+t];
28                     }
29                 }
30             }
31         }
32         int id=0;
33         double ans=0;
34         for(int i=1; i<=num; i++)
35         {
36             if(dp[i][n]>ans)
37                 ans=dp[id=i][n];
38         }
39         printf("%d\n",id);
40     }
41     return 0;
42 }