题意:淘汰赛制,2^n(n<=7)个队员.给出相互PK的输赢概率矩阵。问谁最有可能赢到最后。
解法:ans[i][j]表示第i个队员第j轮胜出的概率。赢到最后需要进行n场比赛。算出每个人赢到最后的ans[i][n]。写出序号的二进制发现一个规律,两个队员i、j如果碰到,那么一定是在第get(i,j)场比赛碰到的。get(i,j)计算的是i和j二进制不同的最高位,这个规律也比较明显。
代码:
/******************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;
#define eps 1e-8
const double pi=acos(-1.0);
typedef long long LL;
const int Max=500;
const int INF=1000000007;
int n;
double num[Max][Max];
bool rem[Max][Max];
double ans[Max][10];
int get(int i,int j)
{
for(int k=n-1;k>=0;k--)
{
if((i&(1<<k))^(j&(1<<k)))
return k;
}
}
int main()
{
while(scanf("%d",&n)==1)
{
memset(ans,0,sizeof ans);
memset(rem,0,sizeof rem);
if(n==-1)
break;
for(int i=0; i<(1<<n); i++)
for(int j=0; j<(1<<n); j++)
scanf("%lf",num[i]+j);
for(int i=0;i<(1<<n);i++)
ans[i][0]=1.0;
for(int k=0;k<n;k++)
{
for(int i=0;i<(1<<n);i++)
for(int j=i+1;j<(1<<n);j++)
{
int t=get(i,j);
if(t!=k)continue;
ans[i][k+1]+=ans[j][k]*ans[i][k]*num[i][j];
ans[j][k+1]+=ans[i][k]*ans[j][k]*num[j][i];
}
}
double t=0;
double sum=0;
int out=0;
for(int i=0;i<(1<<n);i++)
{
if(t<ans[i][n])
{
t=ans[i][n];
out=i;
}
}
cout<<out+1<<endl;
}
return 0;
}