Algorithm 根据级别匹配团队中的球员

Algorithm 根据级别匹配团队中的球员,algorithm,data-structures,matching,Algorithm,Data Structures,Matching,我在想一种方法,让n名球员在3人一组的情况下比赛(n很可能不会超过30人,是3的倍数)。匹配将基于他们的等级(数字越低,玩家的技能越高) 我认为合理的目标是,为了匹配团队中的球员,团队平均排名之间的最大差异(每个团队排名的总和除以3)应尽可能小(即平均排名最高的团队和平均排名最低的团队之间的差异应尽可能小) 我想尝试所有可能的排列,但那是不可能的,因为复杂性将是n!(输入很容易超过20或更多) 我能想到的唯一可行(但非常幼稚)的解决方案如下: 假设我们有12名球员需要在团队中进行匹配。我们将根据

我在想一种方法,让n名球员在3人一组的情况下比赛(n很可能不会超过30人,是3的倍数)。匹配将基于他们的等级(数字越低,玩家的技能越高)

我认为合理的目标是,为了匹配团队中的球员,团队平均排名之间的最大差异(每个团队排名的总和除以3)应尽可能小(即平均排名最高的团队和平均排名最低的团队之间的差异应尽可能小)

我想尝试所有可能的排列,但那是不可能的,因为复杂性将是n!(输入很容易超过20或更多)

我能想到的唯一可行(但非常幼稚)的解决方案如下: 假设我们有12名球员需要在团队中进行匹配。我们将根据等级对其进行排序,然后将排序后的列表分为3部分,每个部分包含4名玩家(前四名玩家技能最高,后四名玩家技能一般,后四名玩家技能最低),然后我将继续从第一部分取第一名玩家,最后一名玩家从最后一部分取最后一名,从第一部分取第二名玩家(最后一名)从最后一部分等等

然后,我将根据平均排名对这两名球员进行排序,然后将中间(第二部分)的第一名球员放入平均排名最高的球队,第二部分的第二名球员放入平均排名第二高的球队,等等

这当然不是一个最优的解决方案。所以我想知道是否有一个可行的方法来解决这个问题,从而产生一个更优化的解决方案

谢谢你

这是一种适合你的简单方法 首先,我们可以考虑一个显然是最优的团队分布:每个团队都有完全相同的等级总和。不幸的是,这并不总是可能的,因为有时候一个团队的平均实力不是一个整数

我们能得到的最接近这个理想的方法是只允许平均实力向上或向下取整的团队。例如,有4支球队和12名球员,一支球队的平均排名总和为19.5,这意味着理想情况下,我们将有两支实力为19的球队和两支实力为20的球队

考虑到所有团队的期望实力,我写了一个快速脚本来创建这些团队。具体来说,它为一个团队随机选择两名球员,然后我们可以计算第三名球员应该是谁。如果想要的第三名球员还没有一支球队,这三名球员组成一支球队,否则我们只需再试一次。如果我们在几次尝试后都无法组建一个团队,我们就完全重新开始

因为这种方法可以随机到达任何排列,并且在卡住时重新启动,所以如果存在最优解,就可以保证找到最优解

有两个缺点:效率可能非常低,而且我还没有证明存在最佳解决方案。然而,对于不到100名玩家,脚本会在合理的时间内找到最优解,从而也证明了最优解的存在

结果 脚本生成的结果是,开箱即用,最多可使用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)

不过,我还是不建议实际使用此代码。

您建议的方法有什么问题?它不是非常理想(我认为),非常随意,而且非常贪婪。我在问是否有更好的方法可以产生更好的解决方案