单循环赛程算法
Monday, 11. February 2008, 04:17:42
任意偶数个队,进行单循环赛,须在最短日期之内举行完全部赛事,请作出日程表之一。
(补充:每个队每天只能举行一场比赛)
并非只有一解的情况也有。
如果有余力,请给出所有可能的答案。
这属于体育赛事日程安排的问题,在数学上,比较接近“柯克曼女生问题”。
例如,4个队的情况下
1-2 3-4
1-3 2-4
1-4 2-3
6个队的情况下
1-2 3-4 5-6
1-3 2-5 4-6
1-4 2-6 3-5
1-5 2-4 3-6
1-6 2-3 4-5
是其一解。
这个问题看起来简单,做起来却颇伤脑筋。
我在网上找了一个比较容易理解的算法,就是一个队不动,其它队组成一个“环”之后旋转,每转一次得到一天的赛程。
用 JavaScript 实现的程序如下:
/**
* 旋转数组
*/
function rotateArray(aOld) {
var iLast = aOld.length - 1;
return [aOld[iLast]].concat(aOld.slice(0, iLast));
}
/**
* 生成日程表
*/
function getLeageSchedule(aTeam) {
var aResult = [];
if(aTeam.length%2 != 0) {
aTeam.push('');
}
var vFirst = aTeam[0];
var aCycle = aTeam.slice(1);
var iHalfLen = aTeam.length/2;
for(var i=0; i<aCycle.length; i++) {
var aLeft = [vFirst].concat(aCycle.slice(iHalfLen).reverse());
var aRight = aCycle.slice(0, iHalfLen);
var aGames = [];
for(var j=0; j<aLeft.length; j++) {
if(aLeft[j] != '' && aRight[j] != '') {
aGames.push(aLeft[j] + '-' + aRight[j]);
}
}
aResult.push(aGames);
aCycle = rotateArray(aCycle);
}
return aResult;
}
//测试
var aTeam = [1,2,3,4,5,6];
var aSchedule = getLeageSchedule(aTeam);
for(var i=0; i<aSchedule.length; i++) {
document.write(aSchedule[i].join(' ') + '
');
}
程序运行的结果如下:
1-2 6-3 5-4
1-6 5-2 4-3
1-5 4-6 3-2
1-4 3-5 2-6
1-3 2-4 6-5
这个算法可能不是太好,只不过比较简单,有一点自己的发挥就是还考虑了奇数队的情况。
问题后面有人用 Ruby 实现了这一算法,总共才8行,实在让人佩服。










