基本上我有很多值需要分成n个不同的组,以便每组的总和尽可能接近其他组的总和?值列表并不是非常长,所以我可能只是暴力强迫它,但我想知道是否有人知道这样做更有效的方法。感谢。
答案 0 :(得分:7)
如果近似解是足够的,那么将数字降序排序,循环遍历它们并将每个数字分配给具有最小总和的组。
groups = [list() for i in range(NUM_GROUPS)]
for x in sorted(numbers, reverse=True):
mingroup = groups[0]
for g in groups:
if sum(g) < sum(mingroup):
mingroup = g
mingroup.append(x)
答案 1 :(得分:3)
这个问题被称为“多路分区问题”,实际上计算难度很大。谷歌搜索它返回了一篇有趣的论文"Multi-Way Number Paritioning,其中作者提到larsmans
建议的启发式,并提出了一些更高级的算法。如果上述启发式还不够,你可以查看论文或者可能联系作者,他似乎正在那个领域进行研究。
答案 2 :(得分:1)
蛮力可能不会像你想象的那样有效......
假设您有100
个变量和20
个群组:
1
变量放入20
个不同的组中,这样可以20
组合。2
个变量分别放入20
个不同的组中,这样就可以20 * 20 = 20^2 = 400
组合。3
个变量分别放入20
个不同的组中,这样就可以20 * 20 * 20 = 20^3 = 8000
组合。100
个变量分别放入20
个不同的组中,这会产生20^100
个组合,这超过了已知Universe中的最小原子数(10^80
)。好的,你可以做得更聪明一点(无论你把第一个变量放在哪里,......)都可以得到像分支和绑定这样的东西,但是那个仍然可以扩展。
因此要么使用快速确定性算法,如larsman
提议。
或者,如果您需要更优化的解决方案并有时间实现它,请查看元启发式算法和实现它们的软件(例如Drools Planner)。
答案 3 :(得分:1)
您可以将数字相加并除以组数。这为您提供了总和的目标值。对数字进行排序,然后尝试获取子集以合计所需的总和。从可能的最大值开始,因为它们将导致总和中的最大变化。一旦您确定了一个不是最佳总和(但接近)的组,您可以重新计算剩余数字的预期总和(超过n-1组),以最小化其余组的最优RMS偏差(如果这是一个度量标准)你关心的)。将这个“预期总和”概念与larsmans答案结合起来,你应该有足够的信息来得出一个快速的近似答案。没有什么是最佳的,但远比随机和运行时间有限。
答案 4 :(得分:1)
您是否知道需要多少组才能提前将其拆分?
您对组的最大大小有限制吗?
针对此问题的变体的一些算法:
算法最小化存储一组文件所需的软盘数量,但保持任何一个文件可以从存储在其上的磁盘中立即读取(而不是将它从存储在2个磁盘上的片段拼凑在一起) - I听说“复制到最适合的软盘”很受欢迎。
使用最少量的减产废料计算切割清单。 Calculating a cutting list with the least amount of off cut waste
在压缩文件中压缩记录的好算法是什么? What is a good algorithm for compacting records in a blocked file?
考虑到N个处理器,如何安排一堆子任务,以便在最短的时间内完成整个作业? multiprocessor scheduling