我有一个整数列表,我需要找到一种方法来获取一个整数子集的最大和,在总和中添加元素,直到总和等于(或大于)固定截止值为止。我知道这看起来与背包相似,但是我不确定它是否等效。
对数组排序并添加最大元素,直到sum <= cutoff不起作用。观察以下列表:
list = [6, 5, 4, 4, 4, 3, 2, 2, 1]
cutoff = 15
对于此列表,以幼稚的方式进行操作会导致总和为15,这是次优的。据我所见,通过添加4 + 4 + 4 + 2 + 6,使用此列表可以达到的最大值是20。如果这只是背包的另一个版本,我可以实施背包解决方案,因为我可能有足够小的清单来解决这个问题,但我想做些更有效的事情。
答案 0 :(得分:1)
首先,总之,最后添加最大元素不会产生更糟的结果。因此,假设第一步将元素从最小到最大排序都是没有害处的。
现在,您使用一种动态编程方法,类似于通常的子集总和。
def best_cutoff_sum (cutoff, elements):
elements = sorted(elements)
sums = {0: None}
for e in elements:
next_sums = {}
for v, path in sums.iteritems():
next_sums[v] = path
if v < cutoff:
next_sums[v + e] = [e, path]
sums = next_sums
best = max(sums.keys())
return (best, sums[best])
print(best_cutoff_sum(15, [6, 5, 4, 4, 4, 3, 2, 2, 1]))
只需做一些工作,就可以将路径从当前的嵌套数组转换为所需的任何格式。
如果您的非负元素列表中包含n
个元素,则截止值为c
,最大值为v
,则此算法将花费时间O(n * (k + v))
< / p>