锦标赛支架算法(NCAA等)

时间:2011-05-20 11:57:20

标签: c# algorithm

我正在尝试在我的程序中实现一个括号(使用C#/。NET MVC)并且我试图找出一些算法。

例如,我有一个这样的括号,有8个条目(A,B,C,D,E,F,G,H)

Bracket Example

我正在试图弄清楚是否有算法

  1. 取决于条目数,找到#of 每轮比赛

  2. 取决于条目数,用于a 特定游戏#,是什么 相应的游戏#在下一个 圆

  3. 例如,在这种情况下,对于8个条目,示例为:

    1. 第1轮比赛有4场比赛。第2轮,第2轮比赛。第3轮,第1场比赛
    2. 第1轮的第2场比赛对应第2轮的第5场比赛。
    3. 我还想过将这些信息存储在一个表格中,但它似乎有点矫枉过正,因为它永远不会改变,但无论如何它仍然存在:

      enter image description here

      任何帮助将不胜感激!

      干杯,

      迪安

5 个答案:

答案 0 :(得分:6)

问题第一部分的C#代码:

// N = Initial Team Count
// R = Zero-Based Round #
// Games = (N / (2 ^ R)) / 2
public double GamesPerRound(int totalTeams, int currentRound) {
    var result = (totalTeams / Math.Pow(2, currentRound)) / 2;

    // Happens if you exceed the maximum possible rounds given number of teams
    if (result < 1.0F) throw new InvalidOperationException();

    return result;
}

解决第(2)部分的下一步是知道给定回合的最小游戏数。一个直观的方法是通过for循环,但可能有一个更好的方法:

var totalTeams = 8;
var selectedRound = 2;
var firstGame = 1;
// If we start with round 1, this doesn't execute and firstGame remains at 1
for (var currentRound = 1; currentRound < selectedRound; currentRound++) {
    var gamesPerRound = GamesPerRound(totalTeams, currentRound);
    firstGame += gamesPerRound;
}

答案 1 :(得分:5)

引用@Yuck完美回答第一个问题。

问题第一部分的C#代码:

// N = Initial Team Count
// R = Zero-Based Round #
// Games = (N / (2 ^ R)) / 2
public double GamesPerRound(int totalTeams, int currentRound) {
    var result = (totalTeams / Math.Pow(2, currentRound)) / 2;

    // Happens if you exceed the maximum possible rounds given number of teams
    if (result < 1.0F) throw new InvalidOperationException();

    return result;
}

继续讨论第二个问题:

//G = current game.
//T = total teams
//Next round game = (T / 2) + RoundedUp(G / 2)
//i. e.: G = 2, T = 8
       //Next round game = (8 / 2) + RoundedUp(2 / 2) = 5
public int NextGame(int totalTeams, int currentGame) {
    return (totalTeams / 2) + (int)Math.Ceiling((double)currentGame / 2);
}

答案 2 :(得分:2)

我实际上是在最近自己解决了这个问题,并且偶然发现(也就是说,我已经解决了,但之前可能已经发现过)一个简洁的递归解决方案。

您从以种子订单排序的列表中的玩家列表开始。这在以后很重要。

整体算法包括将玩家列表分成两个,然后创建两个子锦标赛。这两个分赛事的获胜者将结束整个锦标赛的总决赛。

必需对象

  • 播放器
    • 名称
    • 种子
  • 匹配
    • 主页球员
    • Away Player
    • 下一场比赛(指向获胜者匹配的指针)

拆分列表

大多数锦标赛将头号种子选手放在第一轮的底部种子选手中。为了做到这一点,我使用了以下算法,但您可以将第一个n / 2玩家放在一个列表中,其余的放在另一个列表中以创建一个锦标赛,种子1和2在第一轮播放(和种子3次播放4次,5次播放6次等。

我会在这里注意到,让顶级种子打底线种子的巧妙之处在于,如果你没有两名球员的力量,这个算法的顶级种子会在早期轮次。

  1. 将第一位玩家带入“左”列表
  2. 选择接下来的两名球员(或最后一名球员)并将其放入“右侧”名单
  3. 拿下两个玩家并将它们放在“左侧”列表中
  4. 从第2步开始重复,直到没有其他玩家。
  5. 当然,如果列表中只有两个玩家,你只需在他们之间创建一个匹配并返回。

    建立锦标赛

    所以你开始说一个64位玩家的名单。你将它分成两个32个玩家的列表,并递归创建两个子竞赛。您递归调用的方法应该返回表示子锦标赛的总决赛(整场锦标赛的半决赛)的匹配。然后你可以创建一个匹配作为整个锦标赛的总决赛,并将半决赛的nextMatch设置为总决赛。

    需要考虑的事项

    • 如果传递的列表中只有两个玩家,则需要打破递归。
    • 如果您的分组为您提供了一个列表,则不应对其进行递归。只需用另一个列表创建一个子锦标赛(它应该只有两个玩家,所以将立即返回一个匹配),将主队设置为单个玩家和子锦标赛的nextMatch
    • 如果您希望能够跟踪轮次,则需要传递递归深度整数 - 在创建子锦标赛时增加它。

    希望这有帮助,如果您需要任何澄清,请告诉我们。)

答案 3 :(得分:1)

所以基本上是淘汰赛。

所以只需要List。

如果团队数量是偶数,算法将始终将第一和第二个团队放在一起。然后将计数器增加2并重复。

如果球队的数量是奇数,除了你随机选择一个“第一个周围”的胜利者并将其与奇数球队对抗之外,几乎可以做同样的事情。

在第一轮之后,你以同样的方式重复算法。

A + 1 C + 1 ...

  

例如,我有一个支架   这有8个条目(A,B,C,D,E,F,G,H)

您应该能够弄清楚如何解析它。这似乎是一个家庭作业问题。

答案 4 :(得分:0)

考虑重新编号游戏(之后您可以随时重新编号)

如果决赛是1 半决赛是2,3 这个问题已经得到了很好的解决方案:ahnentafel(德语为祖先表)已经被系谱学家使用了很长时间 - http://en.wikipedia.org/wiki/Ahnentafel

其中一个有趣的部分是游戏的二进制表示法#给出了很多关于锦标赛结构以及比赛所在树的位置的信息。

同时请注意,因为每场比赛都会淘汰1名参赛者,对于n个参赛者,将会有n-1场比赛