http://poj.org/problem?id=3071
推方程不难,但是难在怎么算
dp[i][j]表示第i场时第j只队伍存活下来的概率
方程:dp[i][j]=sigma(dp[i-1][j]*p[j][k]*dp[i-1][k])
j,k在同一场的条件:if(((k>>(i-1))^1)==(j>>(i-1)))即判断k的第i位前的数没有比过的是否与j的在同一棵子树上。(i从1取,j,k从0取)题解参考 http://blog.csdn.net/pbj1203/article/details/6950450
//#pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <iostream> #include <iomanip> #include <cmath> #include <map> #include <set> #include <queue> using namespace std; #define ls(rt) rt*2 #define rs(rt) rt*2+1 #define ll long long #define ull unsigned long long #define rep(i,s,e) for(int i=s;i<e;i++) #define repe(i,s,e) for(int i=s;i<=e;i++) #define CL(a,b) memset(a,b,sizeof(a)) #define IN(s) freopen(s,"r",stdin) #define OUT(s) freopen(s,"w",stdout) const ll ll_INF = ((ull)(-1))>>1; const double EPS = 1e-8; const int INF = 100000000; const int MAXN = 1000; double p[MAXN][MAXN],dp[MAXN][MAXN]; int N,n; int solve() { CL(dp,0); rep(i,0,n)///////// dp[0][i]=1; repe(i,1,N) rep(j,0,n) rep(k,0,n) if(((k>>(i-1))^1) == (j>>(i-1))) dp[i][j]+=dp[i-1][j]*dp[i-1][k]*p[j][k]; int ans=-1; dp[0][0]=-1; rep(j,0,n) if(dp[N][j]>dp[0][0]) { ans=j; dp[0][0]=dp[N][j]; } return ans+1; } int main() { while(~scanf("%d",&N) && N!=-1) { n=1<<N; rep(i,0,n) rep(j,0,n) scanf("%lf",&p[i][j]); printf("%d\n",solve()); } return 0; }