题目链接:https://www.nowcoder.com/acm/contest/144/A
题目大意:有2^n个歌手,每个歌手会准备n首歌去唱,每首歌有它的分数,分数高的就赢。两两相比,赢的人继续两两相比,直到冠军出来。
分析:用一个二维数组保存每个比赛歌手准备的歌曲,并且用该数组继续保存每轮胜者还可以唱的歌曲。可以知道,每个歌手要保证自己每场都赢,就要用比对手最高分歌曲还高的歌曲唱,并且在符合上述条件下,尽量选择分低的(贪心)。
#include<iostream>
using namespace std;
#include<cmath>
#include <algorithm>
#include<cstring>
#include<algorithm>
int a[20000][20];
int main()
{
int t;
cin>>t;
int k=1;
while(t--){
int n;
cin>>n;
int num=pow(2,n);
for(int i=0;i<num;i++){
for(int j=0;j<n;j++)
cin>>a[i][j];
a[i][n]=i+1; //这里用a[i][n]来保存选手序号,因为下面每次去比,选手的序号和它在
//二维数组第一维的坐标是不一样的,所以特别记录一下
}
for(int i=0;i<num;i++)
sort(a[i],a[i]+n); //排序
while(1){
int k=0;
for(int i=0;i<num;i+=2){
if(a[i][n-1]>a[i+1][n-1]){
for(int j=0;j<n;j++){
if(a[i][j]>a[i+1][n-1]){
a[i][j]=-1; //标记已经唱过的歌曲
break;
}
}
int b=0;
for(int j=0;j<=n;j++){ //覆盖
if(a[i][j]!=-1)
a[i/2][b++]=a[i][j];
}
}else{
for(int j=0;j<n;j++){
if(a[i+1][j]>a[i][n-1]){
a[i+1][j]=-1;
break;
}
}
int b=0;
for(int j=0;j<=n;j++){
if(a[i+1][j]!=-1)
a[i/2][b++]=a[i+1][j];
}
}
}
num/=2;
if(num==1) break; // n==1时,冠军就出来了
n=n-1;
}
printf("Case #%d: %d\n",k++,a[0][0]); //最后的情况下,数组里只有选手序号了
}
return 0;
}