我最近研究了一些东西并与Donald Knuth见面。但是我找不到适合我问题的算法。
问题我们与n名球员有联赛。每个星期他们都有一个匹配。在n-1周内,每支球队都互相争斗。每天有n / 2场比赛。但是一支球队一周只能打一次。如果我们生成一个(n / k)组合,我们得到所有组合......(假设k = 2)但我需要按正确的顺序引入它们。
我的第一个建议是......不是最好的建议。我刚做了一个数组,然后让计算机尝试,如果他找到正确的方法。如果没有,回到开始,洗牌阵列再做一次,好吧,我用PHP编程(n = 8),什么出来工作,但需要很多时间,而对于n = 16,它给了我一个超时同样。
所以我想如果我们找到一个算法,或者任何人都知道一本涵盖这个问题的书。
这是我的代码: http://pastebin.com/Rfm4TquY
答案 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));