我列出了10名球员,每名球员都有各自的技能分数。我试图将他们组织成2个5人的团队,每个团队的总技能分数尽可能接近。
对每个组合进行迭代显然效率不高,因为相同的团队将会出现。
是否有一个python库或函数可以有效地解决这个问题,或者至少只是迭代正确的组合?
迭代超过10!如果这是最简单的答案,那么组合就不会那么糟糕。
答案 0 :(得分:1)
正如您所说,找到完美的解决方案对于此问题集非常复杂,但您可以尝试使用贪心方法。
说每个玩家' P'有这些技能得分保龄球(bw)击球(b)& fielding(f)现在你可以用样本方程K = 2*bw+2*b+f
现在你所要做的就是将10名队员分成2队,每队k/2+k/2
左右,如果你使用贪婪的方法,这很简单。
您可以在Wikipedia
中找到此处的实施方案def find_partition(int_list):
"returns: An attempt at a partition of `int_list` into two sets of equal sum"
A = set()
B = set()
for n in sorted(int_list, reverse=True):
if sum(A) < sum(B):
A.add(n)
else:
B.add(n)
return (A, B)
<强>更新强>: 上面的代码并没有考虑团队规模的质量,关于这可能是有用的讨论
https://cs.stackexchange.com/questions/33697/partition-partition-with-constraint-of-equal-size
答案 1 :(得分:1)
虽然不是一个完美的解决方案,但你能否根据平均水平获得普通玩家技能并对n个玩家进行排名。
然后根据这些值,使用一些启发式试图在两个团队中“平衡”这些玩家。 简单的例子就是分配这样的团队(排名最高= 10,排名最低= 1)
第1队= 10 7 6 3 1
第2队= 9 8 5 4 2
同样,不完美,但比10便宜得多!搜索。
答案 2 :(得分:1)
我用itertools.combinations
解决了这个问题,并通过浏览第一个团队的每个组合并使用剩下的玩家作为第二个团队来设置,搜索空间减少到只有252个组合。
from itertools import combinations
# random dictionary of players and scores
players = {
'abc': 1234,
'bcd': 2345,
'cde': 3456,
'def': 4567,
'efg': 5678,
'fgh': 6789,
'ghi': 7891,
'hij': 8912,
'ijk': 9123,
'jkl': 7410
}
closest_difference = None
all_players_set = set(players.keys())
for team_a in combinations(players.keys(), 5):
team_a_set = set(team_a)
team_b_set = all_players_set - team_a_set
team_a_total = sum([players[x] for x in team_a_set])
team_b_total = sum([players[x] for x in team_b_set])
score_difference = abs(team_a_total - team_b_total)
if not closest_difference or score_difference < closest_difference:
closest_difference = score_difference
best_team_a = team_a_set
best_team_b = team_b_set
print("\nTeam a:")
for player in best_team_a:
print(player)
print("with a score of " + str(sum([players[x] for x in best_team_a])))
print("\nTeam b:")
for player in best_team_b:
print(player)
print("with a score of " + str(sum([players[x] for x in best_team_b])))