452. 解码锦标赛
题目描述
明光村迎来了一年一度的盛世——解码锦标赛,有 2^N 次个队伍从世界各村赶来参与比赛,编号为 1 - 2^N。赛制为每一轮晋级一半队伍,按序号大小两两比赛,淘汰弱者。一轮结束后,所有的胜者进入下一轮,依旧是按顺序两两比赛。比如第一轮就是 1 vs 2, 3 vs 4 ... 2^N - 1 vs 2^N。在一旁围观的 Mays 学姐告诉你,N次比赛后的胜者是唯一的。现在你拿到了一份各个参赛队伍的对抗胜率表 win,为 2^N * 2^N 的矩阵, win[i][j] 为一位小数,代表i胜j的概率。
你能告诉 Mays 学姐最有可能获得世界冠军的是那支队伍吗?
输入格式
多组数据。每组第一行为 N ,N <= 8,接下来 N 行 N 列为对抗胜率矩阵。 保证 win[i][j] + win[j][i] = 1 (i != j)。 以 N=0 结束输入。
输出格式
对每组数据,输出胜率最大的队伍的序号。如果最大的两个概率相差不到 0.001,则认为胜率相等,输出序号最小者。
输入样例
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
2
0.0 0.8 0.1 0.4
0.2 0.0 0.2 0.6
0.9 0.8 0.0 0.3
0.6 0.4 0.7 0.0
0
输出样例
2
4
赛中提交:NULL
赛后AC:Y
题目大意:
有2的n次方个人伍参加比赛,采用两两淘汰晋级制(七龙珠的武道大会),求最后胜率最大的人。
思路:
也就是说要决出最终胜者,一个人一共要打n场比赛。
很明显这是一个dfs的题目,在一个完美二叉树上做递归运算,再加上记忆化搜索优化时间
递推式:
dp[i][j]表示第i号选手在第j次比赛中获胜的概率。
p[i][j]表示第i号选手击败第j号选手的概率
dp[i][j]=dp[i][j-1]*segma(dp[k][j-1]*p[i][k]) (k为i在第n次比赛中的兄弟树的所有最末尾的孙子序号)
下面是AC代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <numeric>
#include <functional>
#define maxn 500
using namespace std;
double dp[maxn][10],p[maxn][maxn];
int n;
const double eps=0.001;
double dfs(int num,int level)
{
if(dp[num][level]!=-1){
//printf("(%d %d):%lf \n",num,level,dp[num][level]);
return dp[num][level];
}
else{
double sum=0;
int tmp1=pow(2,level-1);
if(((num-1)/tmp1)%2==0){
for(int i=((num-1)/tmp1+1)*tmp1;i<((num-1)/tmp1+2)*tmp1;i+=1){
sum+=dfs(i+1,level-1)*p[num][i+1];
}
}
else{
for(int i=((num-1)/tmp1-1)*tmp1;i<((num-1)/tmp1)*tmp1;i+=1){
sum+=dfs(i+1,level-1)*p[num][i+1];
}
}
//printf("aaaa%lf\n",sum);
return dp[num][level]=dfs(num,level-1)*sum;
}
}
int main()
{
while(1){
scanf("%d",&n);
if(!n){
break;
}
int N=pow(2,n);
for(int i=1;i<=N;i+=1){
for(int j=1;j<=n;j+=1){
dp[i][j]=-1.0;
}
}
for(int i=1;i<=N;i+=1){
for(int j=1;j<=N;j+=1){
scanf("%lf",&p[i][j]);
if((i%2==0&&j==i-1)||(j%2==0&&i==j-1)){
dp[i][1]=p[i][j];
}
}
}
double maxp=0,tmp;
int ans=0;
for(int i=1;i<=N;i+=1){
tmp=dfs(i,n);
//printf("--%d %lf\n",i,tmp);
if(tmp>maxp+eps){
maxp=tmp;
ans=i;
}
}
printf("%d\n",ans);
}
return 0;
}