Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 选择两队进行每轮比赛,重复前最大限度地暴露_Algorithm_Combinatorics_Schedule - Fatal编程技术网

Algorithm 选择两队进行每轮比赛,重复前最大限度地暴露

Algorithm 选择两队进行每轮比赛,重复前最大限度地暴露,algorithm,combinatorics,schedule,Algorithm,Combinatorics,Schedule,我正在写一个运动日程生成器。假设T队为偶数,每轮G场比赛为T/2的倍数,R轮,我希望生成符合标准的时间表: 所有球队在一轮中的比赛次数相同。 团队组合在重复之前已完全耗尽。 我有一个算法,大部分时间都有效,但并不总是有效。这一点在问题的末尾有详细说明。我如何修复或替换此算法,以便对所有合理的输入稳健地工作 这个问题类似于和,但有不同的要求 例如,假设有T=4个团队。这给了我们6个可能的游戏: (T0,T1) (T0,T2) (T0,T3) (T1,T2) (T1,T3) (T2,T3)

我正在写一个运动日程生成器。假设T队为偶数,每轮G场比赛为T/2的倍数,R轮,我希望生成符合标准的时间表:

所有球队在一轮中的比赛次数相同。 团队组合在重复之前已完全耗尽。 我有一个算法,大部分时间都有效,但并不总是有效。这一点在问题的末尾有详细说明。我如何修复或替换此算法,以便对所有合理的输入稳健地工作

这个问题类似于和,但有不同的要求

例如,假设有T=4个团队。这给了我们6个可能的游戏:

(T0,T1)  (T0,T2)  (T0,T3)  (T1,T2)  (T1,T3)  (T2,T3)
如果每轮有G=4场比赛,那么第一轮不能是这组比赛

(T0,T1)  (T0,T2)  (T0,T3)  (T1,T2)
…因为T0可以玩3次,但T3只可以玩一次,这违反了要求1。相反,第一轮可能是这样的,每个队都可以打两场比赛:

(T0,T1)  (T2,T3)  (T0,T2)  (T1,T3)
如果在第二轮重复相同的一组游戏,那么两个游戏T1、T2和T0、T3将永远不会违反要求2。所以,在我们开始新的比赛之前,我们希望确保他们能进入第二轮。T=4、G=4、R=5的有效时间表为:

(T0,T1)  (T2,T3)  (T0,T2)  (T1,T3)
(T0,T3)  (T1,T2)  (T0,T1)  (T2,T3)
(T0,T2)  (T1,T3)  (T0,T3)  (T1,T2)
(T0,T1)  (T2,T3)  (T0,T2)  (T1,T3)
(T0,T3)  (T1,T2)  (T0,T1)  (T2,T3)
如图所示,对于较大的R值,一轮中的一组博弈最终可以重复

我的算法是这样工作的:

计算可能的游戏中所有独特的两队组合。将此列表另存为currentPool。 创建一个名为otherPool的空列表。 对于每轮,G次执行以下操作: 将游戏中每一队在本轮中被观看的次数相加,在currentPool中找到总和最低的游戏。 将游戏添加到回合中。 将游戏从当前池移动到其他池。 如果currentPool为空,请交换currentPool和otherPool。 对于许多合理的T、G和R值,该算法都有效。然而,有些组合失败了。例如,当T=6、G=3、R=5时,它生成以下计划:

(T0,T1)  (T2,T3)  (T4,T5)
(T0,T2)  (T1,T3)  (T0,T4)
(T0,T3)  (T1,T2)  (T0,T5)
(T1,T4)  (T2,T5)  (T3,T4)
(T1,T5)  (T2,T4)  (T3,T5)
第一轮是正确的,但在第二轮,T0打了两次,T5再也没有上场。在第二轮中选择T0、T2和T1、T3后,问题很容易发现。唯一可能满足要求1的游戏是T4、T5,但该游戏已在第一轮中使用,并且在所有15个独特的游戏用完之前,不得重复使用要求2。算法一开始是死路一条,无法回头

最后,为了完整起见,这里是所描述算法的JavaScript版本。以下是成功运行的示例输出:

let schedule = singleFieldSchedule({
    teams            : 8,
    maxGamesPerRound : 12,
    rounds           : 8
})
console.log(schedule.map(round => round.map(game => `(T${game[0]},T${game[1]})`).join('  ')).join('\n') )

(T0,T1) (T2,T3) (T4,T5) (T6,T7) (T0,T2) (T1,T3) (T4,T6) (T5,T7) (T0,T3) (T1,T2) (T4,T7) (T5,T6)
(T0,T4) (T1,T5) (T2,T6) (T3,T7) (T0,T5) (T1,T4) (T2,T7) (T3,T6) (T0,T6) (T1,T7) (T2,T4) (T3,T5)
(T0,T7) (T1,T6) (T2,T5) (T3,T4) (T0,T1) (T2,T3) (T4,T5) (T6,T7) (T0,T2) (T1,T3) (T4,T6) (T5,T7)
(T0,T3) (T1,T2) (T4,T7) (T5,T6) (T0,T4) (T1,T5) (T2,T6) (T3,T7) (T0,T5) (T1,T4) (T2,T7) (T3,T6)
(T0,T6) (T1,T7) (T2,T4) (T3,T5) (T0,T7) (T1,T6) (T2,T5) (T3,T4) (T0,T1) (T2,T3) (T4,T5) (T6,T7)
(T0,T2) (T1,T3) (T4,T6) (T5,T7) (T0,T3) (T1,T2) (T4,T7) (T5,T6) (T0,T4) (T1,T5) (T2,T6) (T3,T7)
(T0,T5) (T1,T4) (T2,T7) (T3,T6) (T0,T6) (T1,T7) (T2,T4) (T3,T5) (T0,T7) (T1,T6) (T2,T5) (T3,T4)
(T0,T1) (T2,T3) (T4,T5) (T6,T7) (T0,T2) (T1,T3) (T4,T6) (T5,T7) (T0,T3) (T1,T2) (T4,T7) (T5,T6)
函数singleFieldSchedule{teams=8,maxGamesPerRound=12,rounds=8}={}{ const uniquePairs=a=>a.reduceres,o1,i,a=>res.concata.slicei+1.mapo2=>[o1,o2],] const teamNames=Array.fromArrayteams.keys const fullExposure=uniquePairsteamNames const zeroTeamCounts=teamNames.mapn=>[n,0] //计算在保持公平的情况下,每个队可以打多少场比赛 const gamespertam=Math.floormaxGamesPerRound/teams*2 const gamesPerRound=gamespertam*团队/2 const schedule=[] 常量池=[fullExposure,[] 设poolidex=0
对于let r=0;r我没有一个理论上完美的解决方案,但我有一个多项式时间的方法,它应该工作得更好

它的核心是最大匹配。在每一轮中,使用边表示尚未进行的游戏。这将更有可能找到有效的解决方案,解决当前算法可能失败的简单情况。特别是,您已保证团队不能在一轮中玩2场游戏,以及尽可能多的未使用游戏我会习惯的

但我们可以通过注意我们可以使用来改进这一点。如果您将每条边的权重设为G^i,其中G是已玩的游戏数,i是自上次玩特定游戏以来的回合数,那么团队不能在一轮中玩2场游戏,我们将玩尽可能多的游戏

这个算法保证了你的第一个条件,并且真诚地努力让你的第二个条件做得很好。但是它不能保证第二个条件。但是如果你有早期的重复,它们会很好地分布


如果你有大量的回合,你可以利用权重条件来确保每个回合的平均使用次数正确。

我没有一个理论上完美的解决方案,但我有一个多项式时间的方法,应该会更好

它的核心是最大匹配。在每一轮中,使用边表示尚未进行的游戏。这将更有可能找到有效的解决方案,解决当前算法可能失败的简单情况。特别是,您已保证团队不能在一轮中玩2场游戏,以及尽可能多的未使用游戏我会习惯的

但是我们可以改进这个b 我注意到我们可以使用。如果将每条边的权重设为G^i,其中G是已玩的游戏数,i是自上次玩特定游戏以来的回合数,则团队不能在一轮中玩2场游戏,我们将玩尽可能多的游戏

该算法保证了您的第一个条件,并真诚地努力使您的第二个条件做得很好。但这并不能保证第二个。然而,如果你有早期的重复,他们将很好地分布


如果你有大量的轮次,你可以根据体重情况进行调整,以确保每个轮次的平均使用次数正确。

制定一个标准的循环时间表。然后,只需按照您希望的每轮匹配数量进行配对

标准赛程将两队配对,每轮轮换,第一队除外。对于六个团队,时间表如下所示;配对垂直相邻:

0 1 2
5 4 3

0 5 1
4 3 2

0 4 5
3 2 1

0 3 4
2 1 5

0 2 3
1 5 4
就是这样:五轮,每队只和另一队比赛一次

如果您有奇数个团队,则指定团队0作为bye

如果您需要6轮比赛,只需按照上面给出的顺序,从左到右选择每一行:

0-5  1-4  2-3  0-4  5-3  1-2 
0-3  4-2  5-1  ... etc.

联盟中有2N支球队,两场比赛之间的差距是N-1场、N场或N+1场。

制定一个标准的循环赛时间表。然后,只需按照您希望的每轮匹配数量进行配对

标准赛程将两队配对,每轮轮换,第一队除外。对于六个团队,时间表如下所示;配对垂直相邻:

0 1 2
5 4 3

0 5 1
4 3 2

0 4 5
3 2 1

0 3 4
2 1 5

0 2 3
1 5 4
就是这样:五轮,每队只和另一队比赛一次

如果您有奇数个团队,则指定团队0作为bye

如果您需要6轮比赛,只需按照上面给出的顺序,从左到右选择每一行:

0-5  1-4  2-3  0-4  5-3  1-2 
0-3  4-2  5-1  ... etc.

联盟中有2N支球队,比赛之间的间隔是N-1、N或N+1场比赛。

在图表中,所有球队可能进行的所有比赛的集合是a,即,每个球队有一个顶点的图表,每对球队都有连接的边

T=6和T=8的完整图

找到所有团队只玩一次的成对游戏就是找到图形的一个关键点:找到与每个顶点接触的边,没有一个顶点被多条边接触

T=6和T=8的完美匹配示例

确保所有可能的游戏都在进行中,找到一组唯一选择每一条边的完美匹配是一个关键。下面是T=6和T=8两种不同的1-因子分解。第一种是手工创建的,而第二种则使用公认答案中描述的循环算法

如果能够为图生成任何单个1-因子分解,则问题的解决方法如下:

创建代表团队数量的完整图的1-因子分解。 计算单队每轮比赛的次数N为2*G/T。 对于每一轮,从1-因子分解中选择N个完美匹配,并使用这些边作为游戏来玩该轮。 在随后的几轮中,使用后续的完美匹配,以便第一轮中未使用的匹配将在以后使用。 所有完美匹配用完后,重复选择完美匹配。 不需要计算所有1-因子分解。这样做将提供球队球员所没有的多样性。例如,在A队与F队比赛的情况下,T=6的上述两个1-因子分解显示了不同的完美匹配。然而,当A队与F队相互比赛时,B队与D队还是C队可能不受影响

此算法的JavaScript版本如下所示:

//使用“循环”算法计算循环调度 // https://en.wikipedia.org/wiki/Round-robin_tournamentScheduling_algorithm 函数roundRobinteams{ const loop=Array.fromArrayteams.keys 常数轮数=[]
对于图中的let i=0;i,所有团队可能进行的所有游戏的集合是a,也就是说,每个团队有一个顶点的图,边连接每对团队

T=6和T=8的完整图

找到所有团队只玩一次的成对游戏就是找到图形的一个关键点:找到与每个顶点接触的边,没有一个顶点被多条边接触

T=6和T=8的完美匹配示例

确保玩所有可能的游戏,找到一组唯一选择每条边的完美匹配是a。以下是T=6和T=8情况的两种不同的1-分解。第一种是手工创建的,而第二种是使用公认答案中描述的循环算法

如果能够为图生成任何单个1-因子分解,则问题的解决方法如下:

创建完整图形的1-因子分解 对球队的数量感到不满。 计算单队每轮比赛的次数N为2*G/T。 对于每一轮,从1-因子分解中选择N个完美匹配,并使用这些边作为游戏来玩该轮。 在随后的几轮中,使用后续的完美匹配,以便第一轮中未使用的匹配将在以后使用。 所有完美匹配用完后,重复选择完美匹配。 不需要计算所有1-因子分解。这样做将提供球队球员所没有的多样性。例如,在A队与F队比赛的情况下,T=6的上述两个1-因子分解显示了不同的完美匹配。然而,当A队与F队相互比赛时,B队与D队还是C队可能不受影响

此算法的JavaScript版本如下所示:

//使用“循环”算法计算循环调度 // https://en.wikipedia.org/wiki/Round-robin_tournamentScheduling_algorithm 函数roundRobinteams{ const loop=Array.fromArrayteams.keys 常数轮数=[]
对于let i=0,这个答案的开头忽略了G,或者更确切地说是假设它是1。后一部分忽略了要求1。我生成的时间表通常要求团队每轮玩3次,并且非常重要的是每个团队每轮有相同的游戏数。不,它不忽略G。我给了你一个6个团队T,4个团队pe的例子r轮G和无限轮r。此解决方案保证每个团队每轮玩2*G/T游戏;如果这不是整数,则某些团队最多只玩一场游戏,并且任何轮的顺序都将保持这种平衡。你是对的,你答案的第一部分是G=3。我很欣赏你的想法你的回答。当每队每轮只有一场比赛时,它仍然只尊重要求1。@Phrogz:我很确定,只要G是你所写的T/2的倍数,它总是尊重1。@Svante啊,你是对的!谢谢你指出这一点。我编辑了答案,以表明使用T/2要求1是尊重的。谢谢你,Prune,谢谢你r答案很好。请参阅我的答案,以获取以图形方式显示这一点的漂亮图片。该答案的开头忽略了G,或者更确切地说,假设它是1。后一部分忽略了要求1。我生成的时间表通常要求团队每轮玩3次,并且非常重要的是,每个团队每轮都有相同的游戏数。不,它不是not忽略G。我给你举了一个例子,6个团队T,每轮G 4场比赛,无限轮R。这个解决方案保证每个团队每轮玩2*G/T场比赛;如果这不是整数,一些团队只会比其他团队多玩一场比赛,任何轮序都会保持这种平衡。你是对的,y的第一部分我们的答案是G=3。我很欣赏你在答案中的想法。当每队每轮只有一场比赛时,它仍然只满足要求1。@Phrogz:我很确定,只要G是你所写的T/2的倍数,@Svante啊,你是对的!谢谢你指出这一点。我编辑了答案来说明这一点对于T/2要求1,我很荣幸。谢谢你,Prune,谢谢你的好答案。请参阅我的答案,以图形方式显示这一点的漂亮图片。谢谢你;我最终没有使用Blossom算法,但进一步研究这一点让我更多地将其作为一个图形来思考,并在此过程中发现各种有用的功能和见解。谢谢你r this;我最终没有使用Blossom算法,但进一步研究这一点让我更多地将其作为一个图表来思考,并在此过程中发现各种有用的特性和见解。