在锦标赛中列出球员,以便每位球员赢得下一场比赛?

时间:2013-10-24 17:11:10

标签: algorithm graph graph-algorithm

给定一个 N人的课程(这由数组int [] a)表示,其中每个人与所有其他人一起玩游戏。每场比赛只涉及2名球员。所以N人将会有 NC2 游戏。

所有游戏都有你的结果。你必须安排队列中的每个人,条件是 a [i]应该用[i-1] 赢得比赛。对于i的所有值都是如此。

我们不需要关心[i]和[i-2]之间的结果。 a [i]可能会以[i-2] 赢或输。

我的方法(我用回溯来解决这个问题):

  • 对于每个人,我们将保留一份与该人一起赢得比赛的人员名单。
  • 将创建一个新的结果数组(长度等于总玩家数。)
  • 第一个位置与每个人反复填补。
  • 结果数组中的下一个位置填充了与前一个人赢得游戏的人。通过遍历该阵列,将从相应的前一个人的获胜列表中拾取该人。

以上解决方案将使用递归方法尝试每条路径。有没有更好的算法?

2 个答案:

答案 0 :(得分:3)

数学上你所拥有的是一种叫做锦标赛图的东西,你试图找到该锦标赛图中的汉密尔顿路径。虽然在任意图中找到汉密尔顿路径的问题是NP难的,但众所周知,每个锦标赛图必须有哈密顿路径,幸运的是它们并不难找到。

一种简单的方法是使用递归。如果图中只有一个节点,那么解决这个问题非常简单:只需在图表中列出一个人。否则,任意选择一些节点。将比赛分成次级锦标赛:击败那个人的所有人中的一个以及那个人输给的所有人中的一个。递归地在每个子锦标赛中获得哈密尔顿路径。然后,将哈密尔顿路径连接在一起,将你在第一步中挑出的人放在他们之间的适当位置。

这个算法有多高效?像quicksort一样,算法的效率取决于你如何将锦标赛分成更小的部分。假设当您选择一个人将比赛分成较小的部分时,您选择胜利数量尽可能接近n / 2的人。这将产生两个较小的比赛,大小约为n / 2。确定选择哪个人需要二次时间,因为你必须查看每个游戏的结果,以计算玩家有多少输赢。这给了我们以下的递归关系:

  

T(n)= 2T(n / 2)+ O(n 2

使用主定理,我们得出这个递归求解为O(n 2 ),这比你最初的想法要快得多。

希望这有帮助!

答案 1 :(得分:1)

这是一个提示:

假设我们已经为满足约束条件的第一批i-1人进行了排序。是否总能将人i插入此列表中?

考虑这些案例:无论是我击败所有第一批i-1人,还是没有人,或其中一些人,但不是所有人。在前2个案例中我可以插入哪个人? (到目前为止,可能有助于为列表中的每个i-1人分配1或0,指示该人是否击败了我。)在第三种情况下,我们可以在他们击败的任何人之间插入人i和任何击败他们的人。这样的一对总是存在吗?如果没有,是否有其他地方我们可以保证能够安全地插入人物?