Arrays 将n名球员分成大小为k且实力相等(或差异最小)的两支球队

Arrays 将n名球员分成大小为k且实力相等(或差异最小)的两支球队,arrays,algorithm,sorting,data-structures,dynamic-programming,Arrays,Algorithm,Sorting,Data Structures,Dynamic Programming,我最近遇到这个问题,;我想了很多,但找不到解决办法: 给出一份有n名实力球员的名单[s1、s2、s3…sn],创建两支大小为k(k)的球队(a和B)≤ n/2),以便: 总强度最大化 强度差异最小化 力量(A)=A队所有队员的力量总和, 力量(B)=B队所有球员的力量总和, 总强度=强度(A)+强度(B), 强度差=abs(强度(A)-强度(B)) 如果总强度相同,则选择强度差异最小的组合 例如: n = 5; k = 2 players: a b c d e stren

我最近遇到这个问题,;我想了很多,但找不到解决办法:

给出一份有n名实力球员的名单[s1、s2、s3…sn],创建两支大小为k(k)的球队(a和B)≤ n/2),以便:

  • 总强度最大化
  • 强度差异最小化
力量(A)=A队所有队员的力量总和,
力量(B)=B队所有球员的力量总和,
总强度=强度(A)+强度(B),
强度差=abs(强度(A)-强度(B))

如果总强度相同,则选择强度差异最小的组合

例如:

n = 5; k = 2  
players:   a  b  c  d  e  
strength:  4  4  2  2  5  

Option  Team A   Team B  Strength  Difference      
  1     [a,b]    [c,e]      15        1
  2     [a,b]    [d,e]      15        1   
  3     [a,c]    [b,e]      15        3
  4     [a,d]    [b,e]      15        3
  5     [a,c]    [b,d]      12        0
  6     [a,d]    [c,b]      12        0
  7     [a,d]    [c,e]      13        1
选项1和选项2是获胜组合,因为它们的总强度为15(最大值),而它们的强度差比选项3和4更接近最小值

我的想法:

如果2k=n,强度已经得到考虑(因为所有元素都会涉及),我们只需要找到两个一半,使这两个总和的差值最小。但是如何有效地找到它呢


如果2k 如评论中所述,这是的一个变体,它本身就是的一个特例。这些确实有动态规划和近似解决方案,您可以适应这个问题。但两个同等规模团队的具体要求意味着非dp和非贪婪解决方案也是可能的

首先,在考虑球队实力差异之前,对总实力进行优化,这意味着当球员人数n为奇数时,可以放弃最弱的球员,而球队的规模k始终为n的一半。如果k作为输入的一部分,则取2×k最强的玩家并丢弃其他玩家

(你可能想知道这个问题实际上是不是先优化强度差,然后优化总强度。如果你找到两个差值为x的子集,然后再找到另外两个差值为y的子集,这意味着你可以将它们组合成两个差值为| x-y |的较大子集。这是一个明显的优化基础。)动态规划方法。)

动态规划解决方案的替代方案

让我们来看一个例子,将n=23(即n=22)名玩家分成两个11人的团队。如果我们使用暴力来查看每个选项,我们会将其中一名玩家保留在团队A中(以避免重复的解决方案),并尝试从其他21名玩家中每10名玩家的组合来完成团队A。这意味着有:

(n-1选择k-1)=(21选择10)=352716个唯一选项

虽然这是一个可行的选项数量,但更多的球员将很快产生大量的选项;例如,将44名球员分成两支22人的队伍将产生超过1012个选项

我们可以通过将初始分割成两个队,然后检查哪1个玩家、2个玩家、10个玩家需要交换来最大限度地减少强度差异,可以大幅减少所需选项的数量。B组的可重复大小相等的子集

我们可以将最初的团队随机分成几组,但如果我们按实力对球员进行排序,并交替地将一名球员添加到a队或B队,这将限制实力D的初始差异,这反过来将更有可能快速找到具有有限交换数目的解决方案(如果存在多个完美解决方案)

然后我们考虑交换1个球员;我们列出A队中所有球员的名单(除了第一个队,我们总是在A队中以避免重复的解决方案)。并从最弱到最强进行排序。我们还制作了一份B队所有球员的名单,并从最弱到最强进行排序。然后我们同时迭代这两份名单,在每一步移动到列表中的下一个值,使a队和B队的当前球员之间的实力差更接近初始值D。

请注意,在嵌套循环中,我们不会将第一个列表中的每个播放器与第二个列表中的每个播放器进行比较。我们只在列表上迭代一次(这类似于在两个数组中查找差异最小的两个整数;请参见示例)

如果我们遇到一对在交换时减少D的玩家,我们存储这对玩家并设置新的D值

现在我们考虑交换2名球员,我们列出了每队2名球员(不包括球员1)和一组B队球员的名单,从最弱的队到强队(增加两名球员的实力)。。然后我们再次迭代这两个列表,寻找一对在交换时会降低D值的对

我们继续对3名、4名、10名球员进行同样的处理。例如23名球员,这些名单的大小为:

           team A    team B

swap  1        10        11
swap  2        45        55
swap  3       120       165
swap  4       210       330
swap  5       252       462
swap  6       210       462
swap  7       120       330
swap  8        45       165
swap  9        10        55
swap 10         1        11
             ----      ----
             1023      2046
因此,我们会找到最佳的交换,这将导致两个团队在最多3069步之后的实力差异最小,而不是暴力算法的352716步

(我们可以通过按10、1、9、2、8、3、7、4、6、5的顺序检查掉期大小,进一步加快存在多个完美解决方案的情况,以找到解决方案,而无需生成更大的列表。)

例如,将44名球员分成两支22人的队伍最多需要6291453个步骤,而不是1012个步骤。通常,最大步骤数为:

2k+2k−1.− 三,

时间复杂度为:

O(2k)

看起来不太好,但是