POJ3071
Description
Consider a single-elimination football tournament involving (2^n) teams, denoted (1, 2, …, 2^n). In each round of the tournament, all teams still in the tournament are placed in a list in order of increasing index. Then, the first team in the list plays the second team, the third team plays the fourth team, etc. The winners of these matches advance to the next round, and the losers are eliminated. After n rounds, only one team remains undefeated; this team is declared the winner.
Given a matrix (P = [p_{ij}]) such that pij is the probability that team i will beat team j in a match determine which team is most likely to win the tournament.
Input
The input test file will contain multiple test cases. Each test case will begin with a single line containing n (1 ≤ n ≤ 7). The next 2n lines each contain 2n values; here, the jth value on the ith line represents pij. The matrix P will satisfy the constraints that pij = 1.0 − pji for all i ≠ j, and pii = 0.0 for all i. The end-of-file is denoted by a single line containing the number −1. Note that each of the matrix entries in this problem is given as a floating-point value. To avoid precision problems, make sure that you use either the double data type instead of float.
Output
The output file should contain a single line for each test case indicating the number of the team most likely to win. To prevent floating-point precision issues, it is guaranteed that the difference in win probability for the top two teams will be at least 0.01.
Sample Input
2
0.0 0.1 0.2 0.3
0.9 0.0 0.4 0.5
0.8 0.6 0.0 0.6
0.7 0.5 0.4 0.0
-1
Sample Output
2
比赛流程是一颗完全二叉树,1和2比,赢的和3,4中赢的比,所以,树高为n
dp[i][j]指第i轮球队 j 赢的概率
(dp[i][j]=sum dp[i-1][j]*dp[i-1][k]*P[j][k])
其中k是第i轮所有能和 j比赛的球队,比如第2轮,1不能和2、5、6、7、8比赛, 其中,j和2已经比完了,j和5-8只可能在第3轮比赛相遇。
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f,MAXN=(1<<7)+2,mod=998244353;
double a[MAXN][MAXN],dp[8][MAXN];
int main(){
int n;
while(scanf("%d",&n)&&n!=-1){
for(int i=1;i<=1<<n;++i)for(int j=1;j<=1<<n;++j)scanf("%lf",&a[i][j]);
for(int j=1;j<=1<<n;++j)dp[0][j]=1;
//dp的下界
for(int i=1;i<=n;++i){
int num=1<<i;//该轮最大能跨越的球队数
//比如第一轮只能1,2两只球队比,第二轮1234四只球队都可能比,但是!
int s=1,e=num;
for(int j=1;j<=1<<n;++j){
if(j>e)s=e+1,e+=num;//第二轮:1-4,5-8能相遇
dp[i][j]=0;
for(int k=s;k<=e;++k){
if(k==j)continue;
dp[i][j]+=dp[i-1][j]*dp[i-1][k]*a[j][k];
a[j][k]=0;//j和k在第i轮比完了,在后面几轮不会再比了
}
}
}
int p=1;
for(int j=1;j<=1<<n;++j)if(dp[n][j]>dp[n][p])p=j;
printf("%d
",p);
}
return 0;
}