題目描述:有n支球隊,編號為0~n-1,隨機兩兩比賽,晉級之後同樣,求一個Result序列,表明最後每支球隊的名次,如果是在同一輪中被淘汰的,那名次相同。其實以前寫過這個題的代碼,不過現在看看覺得寫得太挫了,所以重新寫一下。
思路分析:
這裡借用歸並排序的思想,其實每次決定兩支要比賽的隊伍的標號相距多少就可以了,假設隊伍i和隊伍i+l比賽,不管最後結果怎樣,默認勝利的那支球隊的編號是存在第i的位置,這樣方便安排下一輪比賽。
將兩支球隊之間的步長跨越從1遍歷到nLen-1,就可以遍歷到所有的球隊,在增大步長的同時,其實就是淘汰掉步長不能覆蓋的隊伍,不是麼?至於一些邊界的判斷,這需要自己好好思考,畢竟別人給的答案都不是自己的東西。
核心代碼如下,有沒有覺得代碼很短很漂亮:
[cpp]
//計算比賽結果
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;//贏了的名次
}
}
}
//計算比賽結果
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函數的定義。
[cpp]
#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;
}