题目描述:有n支球队,编号为0~n-1,随机两两比赛,晋级之后同样,求一个Result序列,表明最后每支球队的名次,如果是在同一轮中被淘汰的,那名次相同。其实以前写过这个题的代码,不过现在看看觉得写得太挫了,所以重新写一下。
思路分析:
这里借用归并排序的思想,其实每次决定两支要比赛的队伍的标号相距多少就可以了,假设队伍i和队伍i+l比赛,不管最后结果怎样,默认胜利的那支球队的编号是存在第i的位置,这样方便安排下一轮比赛。
将两支球队之间的步长跨越从1遍历到nLen-1,就可以遍历到所有的球队,在增大步长的同时,其实就是淘汰掉步长不能覆盖的队伍,不是么?至于一些边界的判断,这需要自己好好思考,毕竟别人给的答案都不是自己的东西。
如果有幸得到青睐,那请转载注明出处:http://blog.csdn.net/kay_zhyu/article/details/8879693
核心代码如下,有没有觉得代码很短很漂亮:
//计算比赛结果
void GetResult(int *Order, int *Result, int nLen)
{
if(!Order || !Result || nLen < 1)
return;
int l,i;
for(l = 1; l < nLen; l <<= 1)
{//l为两个队伍之间的跨越的步长
for(i = 0; i < nLen - l; i += l + l)
{
if(rand() < RAND_MAX / 2)
{//保证Order[i]胜Order[i+l]
swap(Order[i], Order[i + l]);
}
Result[Order[i + l]] = nLen / (l + l) + 2;//输了的名次
Result[Order[i]] = nLen / (l + l) + 1;//赢了的名次
}
}
}
下面给出辅助函数和main函数的定义。
#include<stdio.h>
#include<stdlib.h>
void swap(int &a, int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
int main()
{
const int N = 30;
int Order[N];
int Result[N];
int n,i;
while(scanf("%d", &n) != EOF)
{
for(i = 0; i < n; ++i)
scanf("%d", &Order[i]);
GetResult(Order, Result, n);
for(i = 0; i < n; ++i)
printf("%d ", Order[i]);
printf("\n");
for(i = 0; i < n; ++i)
printf("%d ", Result[Order[i]]);
printf("\n");
}
return 0;
}