一种适用于您的界限的简单方法
首先,我们可以考虑一个明显最优的团队分布:每个团队的排名总和完全相同。不幸的是,这并不总是可行的,因为有时团队的平均力量不是整数。
我们能得到的最接近这个理想的方法是只允许平均实力的球队向上或向下取整。例如,有 4 支球队和 12 名球员,一支球队的平均排名总和为 19.5,这意味着理想情况下,我们将有两支力量为 19 的球队和两支力量为 20 的球队。
考虑到所有团队的理想实力,我编写了一个快速脚本来组建这些团队。具体来说,它会随机选择两名球员组成一支球队,然后我们可以计算出第三名球员应该是谁。如果所需的第三个玩家还没有团队,这三个人组成一个团队,否则我们只需再试一次。如果多次尝试仍无法组队,我们将重新开始。
因为这种方法可以随机到达任意排列,卡住时会重新启动,如果存在则保证找到最优解。
有两个缺点:它可能非常低效,而且我还没有证明存在最佳解决方案。然而,对于少于 100 名玩家,脚本会在合理的时间内找到最优解,从而也证明最优解存在。
结果
脚本生成的结果是 in this pastebin,开箱即用,最多可用于 42 支球队(126 名球员)。
Python 脚本本身写得很糟糕,优化很差,而且通常很糟糕,以至于我很犹豫将其上传到这里。我希望任何人都能够根据上述总体思路制作出更好的版本。但是,SO要求pastebin链接要附上代码,所以这里是:
from __future__ import division, print_function
import random
import sys
def solve(teams, players):
playerset = set(players)
result = None
while True:
result = []
taken = set()
for team in teams:
for _ in range(len(teams) * 10):
first = random.choice(players)
while first in taken:
first = random.choice(players)
second = random.choice(players)
while second == first or second in taken or not team - first - second in playerset or team - first - second in [first, second]:
second = random.choice(players)
third = team - first - second
if third not in taken:
result.append(sorted([first, second, third]))
taken.add(first)
taken.add(second)
taken.add(third)
break
else:
break
else:
print_solution(result)
return
def print_solution(result):
for i, team in enumerate(result):
print("{}: {}, {}, {}".format(i+1, *team))
print()
sys.stdout.flush()
def get_team_strengths(N_teams, players):
s = sum(players)
mean = s/N
target = mean*3
teams = [int(target)]*N_teams
teams.sort()
while sum(teams) != s:
if sum(teams) > s:
teams[-1] -= 1
else:
teams[0] += 1
teams.sort()
return teams
for N_teams in range(1, 43):
N = N_teams * 3
players = list(range(1, N+1))
teams = get_team_strengths(N_teams, players)
print("{} teams:".format(N_teams))
solve(teams, players)
不过,我不建议实际使用此代码。