题意:有2^n支队伍进行比赛,
每一轮第一支队伍和第二支队伍比赛,
第三支和第四支队伍比赛,以此类推。
输了的消除掉,再按此规律继续下一轮。
每行给出这支队伍打败各支队伍的几率,
每一轮第一支队伍和第二支队伍比赛,
第三支和第四支队伍比赛,以此类推。
输了的消除掉,再按此规律继续下一轮。
每行给出这支队伍打败各支队伍的几率,
求出那支队伍获胜几率最大。
dp[i][j]表示第i轮第j队获胜的概率,pp[j][k]表示j对战k的胜率
dp[i][j]=sigma(dp[i-1][j]*dp[i-1][k]*pp[j][k]);即j,k队都在第i轮前不能淘汰.然后在第i轮j打败k。
按照比赛规则。每轮比赛过后都要进行重排。这个重排规律很简单
p=j>>(i-1)为第j个球队在i前一轮的编号,q为第k个球队在i前一轮的编号。
他们两队应该在此轮相邻,则p!=q, p/2==q/2.
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn=1<<8;
double dp[maxn][maxn];
double pp[maxn][maxn];
int main()
{
int n;
while(~scanf("%d",&n))
{
if(n==-1) break;
int N=1<<n;
for(int i=0;i<N;++i)
for(int j=0;j<N;++j)
scanf("%lf",&pp[i][j]);
memset(dp,0,sizeof(dp));
for(int j=0;j<N;++j) dp[0][j]=1;//初始置1
for(int i=1;i<=n;++i)
for(int j=0;j<N;++j)
for(int k=0;k<N;++k)
if(j!=k)
{
int p=j>>(i-1),q=k>>(i-1);
if(p==q||(p/2)!=(q/2)) continue;
dp[i][j]+=dp[i-1][j]*dp[i-1][k]*pp[j][k];
// printf("%d th: %d %d %lf\n",i,j,k,dp[i-1][j]*dp[i-1][k]*pp[j][k]);
}
int ans=0;
for(int j=0;j<N;++j)
if(dp[n][ans]<dp[n][j])
ans=j;
// printf("%d %lf\n",ans+1,dp[n][ans]);
printf("%d\n",ans+1);
}
return 0;
}