循环赛的调度算法?

时间:2011-07-11 10:01:15

标签: algorithm combinatorics

我最近研究了一些东西并与Donald Knuth见面。但是我找不到适合我问题的算法。

问题我们与n名球员有联赛。每个星期他们都有一个匹配。在n-1周内,每支球队都互相争斗。每天有n / 2场比赛。但是一支球队一周只能打一次。如果我们生成一个(n / k)组合,我们得到所有组合......(假设k = 2)但我需要按正确的顺序引入它们。

我的第一个建议是......不是最好的建议。我刚做了一个数组,然后让计算机尝试,如果他找到正确的方法。如果没有,回到开始,洗牌阵列再做一次,好吧,我用PHP编程(n = 8),什么出来工作,但需要很多时间,而对于n = 16,它给了我一个超时同样。

所以我想如果我们找到一个算法,或者任何人都知道一本涵盖这个问题的书。

这是我的代码: http://pastebin.com/Rfm4TquY

3 个答案:

答案 0 :(得分:45)

经典算法的工作原理如下:

团队数量1..n。 (这里我将采用n = 8。)

将所有团队分成两行。

1 2 3 4
8 7 6 5

列显示哪一支队伍将参加该轮比赛(1比8,2比7比......)。

现在,保持1固定,但轮换所有其他球队。在第2周,你得到

1 8 2 3
7 6 5 4

并且在第3周,你得到

1 7 8 2
6 5 4 3

这将持续到第n-1周,在这种情况下,

1 3 4 5
2 8 7 6

如果n是奇数,那么做同样的事情但是添加一个虚拟团队。与虚拟团队匹配的任何人在那一周获得bye

答案 1 :(得分:4)

这是JavaScript中的代码。

function makeRoundRobinPairings(players) {
  if (players.length % 2 == 1) {
    players.push(null);
  }

  const playerCount = players.length;
  const rounds = playerCount - 1;
  const half = playerCount / 2;

  const tournamentPairings = [];

  const playerIndexes = players.map((_, i) => i).slice(1);

  for (let round = 0; round < rounds; round++) {
    const roundPairings = [];

    const newPlayerIndexes = [0].concat(playerIndexes);

    const firstHalf = newPlayerIndexes.slice(0, half);
    const secondHalf = newPlayerIndexes.slice(half, playerCount).reverse();

    for (let i = 0; i < firstHalf.length; i++) {
      roundPairings.push({
        white: players[firstHalf[i]],
        black: players[secondHalf[i]],
      });
    }

    // rotating the array
    playerIndexes.push(playerIndexes.shift());
    tournamentPairings.push(roundPairings);
  }

  return tournamentPairings;
}

已更新: 修复了评论中报告的错误

答案 2 :(得分:0)

我使用可重用的函数(受 varun 启发)为此做了一个更新的解决方案:

const testData = [
  "Red",
  "Orange",
  "Yellow",
  "Green",
  "Blue",
  "Indigo",
  "Violet",
];

const matchParticipants = (participants) => {
  const p = Array.from(participants);
  if (p % 2 == 1) {
    p.push(null);
  }
  const pairings = [];
  while (p.length != 0) {
    participantA = p.shift();
    participantB = p.pop();
    if (participantA != undefined && participantB != undefined) {
      pairings.push([participantA, participantB]);
    }
  }
  return pairings;
};

const rotateArray = (array) => {
  const p = Array.from(array);
  const firstElement = p.shift();
  const lastElement = p.pop();
  return [firstElement, lastElement, ...p];
};

const generateTournament = (participants) => {
  const tournamentRounds = [];
  const rounds = Math.ceil(participants.length / 2);
  let p = Array.from(participants);
  for (let i = 0; i < rounds; i++) {
    tournamentRounds.push(matchParticipants(p));
    p = rotateArray(p);
  }
  return tournamentRounds;
};

console.log(generateTournament(testData));