题意:有2^n支队,每次相邻的两支队打比赛,问最后哪支队夺冠的概率最大。
思路:用dp[i][j]表示第i轮第j支队获胜的概率,那么我们可以得到状态转移方程
dp[i][j]=sigma(dp[i-1][j]*dp[i-1][k]*p[j][k]),但要注意到在第i轮j并不是和剩下每个队都可以进行比赛,他只可以和与他左或右相邻的(2^(i-1))支队伍打比赛,那么我们在转移时计算出这个区间就可以了。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<ctime>
#define eps 1e-6
#define LL long long
#define pii pair<int, int>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
//const int maxn = 100 + 5;
//const int INF = 0x3f3f3f3f;
double p[150][150];
double dp[10][150];
int main() {
//freopen("input.txt", "r", stdin);
int n;
while(scanf("%d", &n)==1 && n!=-1) {
memset(dp, 0, sizeof(dp));
int tot = 1<<n;
for(int i = 0; i < tot; i++)
for(int j = 0; j < tot; j++) scanf("%lf", &p[i][j]);
for(int i = 0; i < n; i++) {
for(int j = 0; j < tot; j++) {
int pos = j / (1<<i), st, ed;
if(pos&1) st = (pos-1)*(1<<i);
else st = (pos+1)*(1<<i);
ed = st + (1<<i);
//if(!i) cout << " " << j << " " << st << " " << ed << endl;
for(int k = st; k < ed; k++) {
if(i) dp[i][j] += dp[i-1][j]*dp[i-1][k]*p[j][k];
else dp[i][j] = p[j][k];
}
//cout << i << " " << j << " " << dp[i][j] << endl;
}
}
double ans = 0; int tag;
for(int i = 0; i < tot; i++) if(ans<dp[n-1][i]) tag = i+1, ans = dp[n-1][i];
cout << tag << endl;
}
return 0;
}