A题 Singing Contest
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
Jigglypuff is holding a singing contest. There are 2n singers indexed from 1 to 2n participating in the contest.
The rule of this contest is like the knockout match. That is, in the first round, singer 1 competes with singer 2, singer 3 competes with singer 4 and so on; in the second round, the winner of singer 1 and singer 2 competes with the winner of singer 3 and singer 4 and so on. There are n rounds in total.
Each singer has prepared n songs before the contest. Each song has a unique pleasantness. In each round, a singer should sing a song among the songs he prepared. In order not to disappoint the audience, one song cannot be performed more than once. The singer who sings the song with higher pleasantness wins.
Now all the singers know the pleasantness of songs prepared by all the others. Everyone wants to win as many rounds as he can. Assuming that singers choose their song optimally, Jigglypuff wants to know which singer will win the contest?
输入描述:
The input starts with one line containing exactly one integer t which is the number of test cases. (1 ≤ t ≤ 10)
For each test case, the first line contains exactly one integer n where 2n is the number of singers. (1 ≤ n ≤ 14)
Each of the next 2n lines contains n integers where aij is the pleasantness of the j-th song of the i-th singer. It is guaranteed that all these 2nx n integers are pairwise distinct. (1 ≤ aij ≤ 109)
输出描述:
For each test case, output "Case #x: y" in one line (without quotes), where x is the test case number (starting from 1) and y is the index of the winner.
示例1
输入
复制
2 1 1 2 2 1 8 2 7 3 4 5 6
输出
复制
Case #1: 2 Case #2: 4
【题目大意】:
举办一个歌唱比赛,一共有2^n位选手,进行n轮比赛,第一轮1、2号选手比赛,3、4号选手比赛....第二轮1、2号选手在第一轮胜出者与3、4号选手在第一轮胜出者比赛,以此类推....
每位选手准备n首歌曲,每首歌曲都有一个快乐值,快乐值高的比赛胜出,且每一首歌的快乐值都是唯一的且只能被演唱一次。所有的选手都知道对方的所有歌曲的快乐值,每个人都会尽可能的去胜出(即采取最优策略)。
提问:最后胜出的选手的下标。
思路:///模拟模拟这道题也不卡时间
因为选手都会采取最优策略,那每一轮选择演唱的歌曲的快乐值肯定会大于对手歌曲中最大的快乐值。若存在这样的歌曲则胜出,否则对手胜出,进入下一轮比赛。然而我们每次演唱的歌曲其实并不要都是快乐值最大的,而是歌曲中快乐值比对方最大快乐值大的第一首歌就行了..绕晕了?[比如:1号选手(3,6,9),2号选手(2,4,5),1号一定会赢,因为2号选手的最优策略一定是演唱快乐值为5的歌曲,而1号选手只需要演唱快乐值为6的歌曲就能胜出,所以并一定是演奏快乐值最大的歌曲就是最优解]
然后我们队伍是采用了一个肥肠骚的做法.....队列数组,就是将数组压入队列中,数组代表的是每一个选手的歌曲的快乐值。如何实现呢.....(菜鸡们不知道set这个牛逼的STL容器总是会各种瞎想办法实现啊)队列中数据类型用的是结构体,然而结构体里写的是数组(用来存n首歌的快乐值),每次都取出前两个元素,即队首和次队首,(都要pop掉)这就是要比较的两个选手,胜出的就push到队尾进行下一轮比赛。
找出胜出队伍很简单,但我们还要找出演奏的歌曲,因为每首歌只能演奏一次,我们对结构体里的数组进行排序,找到第一个大于淘汰方的最大的快乐值,(这里应该可以用upper_bound()吧,不过我们没用直接找的反正n也不大),再将这个快乐值变成负数做个标记。!!!一定要记得push胜出选手吖吖....
最后queue的size为1的时候就可以输出了,对了,要记得记录一下选手的号码。
这个题也可以用stl容器set来做...不过比赛的时候并不会...学无止境。
代码:
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
bool cmp(const int q,const int w)
{
return q>w;
}
struct node
{
int x[16];
int cnt;
};
int main()
{
std::ios::sync_with_stdio(false);
int t;
cin>>t;
for(int p=1; p<=t; p++)
{
queue<node> q;
int n;
cin>>n;
int a[16];
node tmp,tmp2;
int num = pow(2,n);
//printf("num=%d\n",num);
for(int i=1;i<=num;i++)
{
for(int j=0;j<n;j++)
{
cin>>tmp.x[j];
}
sort(tmp.x,tmp.x+n,cmp);
tmp.cnt=i;
q.push(tmp);
}
//printf("size=%d\n",q.size());
while(q.size()>1)
{
tmp = q.front();
q.pop();
tmp2=q.front();
q.pop();
if(tmp.x[0]>tmp2.x[0])
{
for(int i=n-1;i>=0;i--)
{
if(tmp.x[i]>tmp2.x[0])
{
tmp.x[i]=-999;
sort(tmp.x,tmp.x+n,cmp);
break;
}
}
q.push(tmp);
}
else
{
for(int i=n-1;i>=0;i--)
{
if(tmp2.x[i]>tmp.x[0])
{
tmp2.x[i]=-999;
sort(tmp2.x,tmp2.x+n,cmp);
break;
}
}
q.push(tmp2);
}
//printf("size=%d\n",q.size());
}
printf("Case #%d: %d\n",p,q.front().cnt);
}
return 0;
}
本文介绍了一个模拟歌唱比赛的算法问题,比赛包含多轮淘汰制,每位选手拥有多首歌曲,每首歌曲有不同的快乐值,选手们采取最优策略选择歌曲以求胜利。

被折叠的 条评论
为什么被折叠?



