题目:
比如order[n] = {4,3,5,8,1......},那么第一轮比赛就是 4对3, 5对8。。。。。。n支队伍比赛,分别编号为0,1,2。。。。n-1,已知它们之间的实力对比关系,存储在一个二维数组w[n][n]中,w[i][j] 的值代表编号为i,j的队伍中更强的一支 所以w[i][j]=i 或者j,现在给出它们的出场顺序,并存储在数组order[n]中。
胜者晋级,败者淘汰,同一轮淘汰的所有队伍排名不再细分,即可以随便排,
下一轮由上一轮的胜者按照顺序,再依次两两比,比如可能是4对5,直至出现第一名
编程实现,给出二维数组w,一维数组order 和 用于输出比赛名次的数组result[n],求出result
思路:
题目中已经明确说明了不需要求出每一个的名次,比赛方法也已经明确给出,因此在算法的设计时就比较明确了,通过简单的例子可以看出比赛过程有一个最多的比赛轮次:log2(n)+1轮。有点像是二叉树的层数。算法中使用了一个辅助的数组来标记下一轮的的名单,以下代码基本上是按照这个思路来的,未仔细测试边界条件
UINT32 w[n][n]; //已知条件
UINT32 order[n]; //已知条件
UINT32 result[n]; //第i个元素对应了i的名次(应该是淘汰批次)
UINT32 GetID(UINT32 list[n] , UINT32 startPos=0)
{//查找第一个不为0的位置
int i = startPos;
for( ;i < n; i++)
{
if( list[i] != 0)
{
return i;
}
}
return n;
}
UINT32* bisai(UINT32 w[n][n],UINT32 order[n])
{
UINT32 result[n];
memset(result,n/2,sizeof(UINT32)*n);
UINT32 nextID[n]; //晋级名单
memset(nextID,1,sizeof(UINT32)*n);
UINT32 i,j;
while(1)
{//比赛开始
for( i = GetID(nextID), j = GetID(nextID,i) ;
i < n&& j < n;
i = GetID(nextID,j),j = GetID(nextID,i))
{
if( i == w[i][j] )//i晋级,j被淘汰
{
nextID[j] = 0; //j被淘汰
--result[i];
}
if( j == w[i][j])
{
nextID[i] = 0; //i被淘汰
--result[j];
}
}
if( i == j)
{//i就是第一名了
break;
}
}
return result;
}