我需要制作体育赛事的时间表。
有30支球队。每支球队必须打8场比赛。这意味着每支球队都不可能再次参加所有其他球队的比赛,但我需要避免这两支球队相互竞争不止一次。
我的想法是生成所有可能的匹配项(针对30个团队:(30*29)/2 = 435 matches
)并从此列表中选择120个匹配项(每个团队匹配8个匹配项:8 * 30 / 2 = 120 matches
)。
这是我遇到困难的地方:我如何选择这120场比赛?我尝试了一些简单的解决方案(列表的第一个匹配,然后是最后一个,依此类推),但它们似乎不适用于30个团队。我还尝试生成所有可能的匹配组合并找到哪一个正在工作但是有30个团队,这是太多的计算时间。
我是否可以实现现有算法?
更新
我需要制作的是一个简单的时间表,而不是消除。每支球队都有8场比赛,就这样。在一天结束时,将不会有一个获胜者。
每支球队都会有自己的赛程安排,而且这个赛程不会因为输赢而改变。规划工作一整天都是不可改变的。
更新2
起初,我不想对我的问题施加太多限制,但似乎没有任何限制(除了每个团队不会相互竞争一次),这只是一个随机挑选的问题8每支球队的比赛。
所以这里有更多细节:
在这项体育赛事期间,有6种不同的运动项目(足球,手球,篮球等)。这意味着有6个同时匹配。每15分钟开始一轮新的比赛。
每支球队必须参加8场比赛,每项运动至少一次。
这6项运动分别在三个不同的地方进行。这意味着在白天,每个团队都必须从一个地方搬到另一个地方。应尽可能减少这些举措。
球队不能连续打两场比赛。
答案 0 :(得分:7)
您可以查看一些已知的匹配方法:
E.g。 Swiss Chess system
编辑:
再次阅读您的要求后 - 每个团队应该只为其他团队打一次,并且不一定要确定胜利者。似乎单个Round Robin系统可以满足您的需求。你可以将任何额外的比赛放在你需要的8之上。
答案 1 :(得分:4)
真的很简单,只需与i
,i-4
,i-3
,i-2
,i-1
,{{组成团队i+1
。 1}},i+2
,i+3
。这可以使用下面的算法来完成。
i+4
<强>输出:强>
import java.util.*;
public class Test {
public static void main(String[] args) {
int TEAMS = 30, MATCHES = 8;
int[] matchCount = new int[TEAMS]; // for a sanity check.
List<Match> matches = new ArrayList<Match>();
for (int team1 = 0; team1 < TEAMS; team1++)
for (int team2 = team1 + 1; team2 <= team1 + MATCHES/2; team2++) {
matches.add(new Match(team1, team2 % TEAMS));
// Just for a sanity check:
matchCount[team1]++;
matchCount[team2 % TEAMS]++;
}
System.out.println(matches);
// Sanity check:
System.out.println(matches.size());
System.out.println(Arrays.toString(matchCount));
}
static class Match {
int team1, team2;
public Match(int team1, int team2) {
this.team1 = team1;
this.team2 = team2;
}
public String toString() {
return team1 + " vs " + team2;
}
}
}
如果您想要更随机的设置,您只需为每个团队分配1到30之间的随机数。
更新为了应对您添加的约束:让 i 匹配运动 i mod 6 。
答案 2 :(得分:2)
你确定你不能得到32支球队:-)?
这会让事情变得更简单 - 有一个标准的锦标赛结构,但每轮比赛的输家都会在他们自己的排行榜中出现。 我认为这最大化了在比赛期间赢得至少一场比赛的球队数量。
有30支球队,你可以让2支球队打出“友谊赛”,并在第一轮比赛中获胜。但组织变得更加复杂。
答案 3 :(得分:0)
我不知道现有的实现,但这里有一个可能的解决方案:
制作三组9支球队,并将每支球队与其他球队配对,这样每支球队都会对其他球队进行一次比赛。现在27支球队中的每支球队都打了8场比赛。
现在选择其余三支球队,每支球队一支。
修改每个团队的一些游戏:
1-2 -> 1-10, 2-10
3-4 -> 3-10, 4-10
5-6 -> 5-10, 6-10
7-8 -> 7-10, 8-10
答案 4 :(得分:0)
经纪人的算法可能有用。有趣的是,我无法在网上找到好的描述,所以我会尝试解释一下这个系统。
实际上,每支球队都会向对方队伍询问比赛得分,并选出得分最高的比赛。每个团队都会重复这一过程并进行匹配。保存生成的计划并计算总分。然后使用不同的起点(即您可以随机化团队顺序),这将再次完成,如果总分更高,则选择此计划。您重复此操作,直到您找到产生高得分的计划或在预定次数的尝试之后。
总得分可以通过每个队伍的行进距离来计算,数字越小越好。显然你不会选择违反规则的比赛(太多相似类型的比赛,相同的球队再次相互比赛)。
得分可能是这样的:
当然BA的问题是为不同的参数找到好的值,所以你需要花一些时间找到它们。
答案 5 :(得分:0)
如果你想要一个简单的算法,它会产生一个时间表,在这个时间表中,团队不会多次相互竞争,这对于给定的参数来说并不难。
以下是10个团队和5个回合的示例,解决方案显示为一个数组,如果schedule [i] [j]的值为零,则团队不会一起玩,如果是一个数字则它显示了他们在哪一轮比赛。
1 2 3 4 5 6 7 8 9 10
1 [0, 5, 0, 4, 0, 3, 0, 2, 0, 1]
2 [5, 0, 4, 0, 3, 0, 2, 0, 1, 0]
3 [0, 4, 0, 3, 0, 2, 0, 1, 0, 5]
4 [4, 0, 3, 0, 2, 0, 1, 0, 5, 0]
5 [0, 3, 0, 2, 0, 1, 0, 5, 0, 4]
6 [3, 0, 2, 0, 1, 0, 5, 0, 4, 0]
7 [0, 2, 0, 1, 0, 5, 0, 4, 0, 3]
8 [2, 0, 1, 0, 5, 0, 4, 0, 3, 0]
9 [0, 1, 0, 5, 0, 4, 0, 3, 0, 2]
10[1, 0, 5, 0, 4, 0, 3, 0, 2, 0]
所以从第一轮的表中(1,10),(2,9),(3,8),(4,7),(5,6),在第二轮比赛中,球队( 1,8),(2,7),(3,6)......等等。
要生成此表,算法相当简单,这里有一些python代码:
#!/bin/env python
def simpleNRooks(size, rounds, schedule):
''' Place n rooks on board so that they don't hit each other in each round,
nor reuse the spots from previous rounds '''
for i in range(size):
for j in range(rounds):
if size-j*2-i-1 < 0:
schedule[i][2*size-j*2-i-1] = j + 1
else:
schedule[i][size-j*2-i-1] = j + 1
# parameters
teams = 10
matches = 5
# prepare the schedule, 0's designate free space
schedule = [[0 for i in range(teams)] for j in range(teams)]
simpleNRooks(teams, matches, schedule)
print 'Final schedule'
for i in range(teams):
print schedule[i]
如果您想要获得不同的数据结构(例如,轮次对的列表),您可以使用相同的原则,但更改循环。
答案 6 :(得分:0)
考虑到新约束,我正在添加一个单独的答案,因为我认为它比添加到我的旧答案更清晰。
将30支队伍分成5组,每队6支队伍:A B C D E
第一期A组和B组比赛。
然后是C&amp; D,E&amp; A,B&amp; C,D&amp; E,用于接下来的4个15分钟段。
所以在5 * 15分钟结束时:每支球队都打了两次,其中至少有一次休息时间。
有20个周期,每个人都玩了8次。
例如,允许B组的一支球队与A,B和B组的其他17支球队中的其他8支球队进行比赛应该很容易。 C组。例如,玩A队对抗B队,然后是B队对阵C队,然后是反向队列,然后是小组,然后是MOD 2,MOD 3,小组之间以及小组内。
这样可以减少旅行时间,确保每个团队都能玩各种游戏类型。但是对于一个组解决这个问题,你可以将相同的解决方案应用于所有其他组吗?