固定截止的子阵列的最大和

时间:2019-06-24 16:41:52

标签: algorithm

我有一个整数列表,我需要找到一种方法来获取一个整数子集的最大和,在总和中添加元素,直到总和等于(或大于)固定截止值为止。我知道这看起来与背包相似,但是我不确定它是否等效。

对数组排序并添加最大元素,直到sum <= cutoff不起作用。观察以下列表:

list = [6, 5, 4, 4, 4, 3, 2, 2, 1]
cutoff = 15

对于此列表,以幼稚的方式进行操作会导致总和为15,这是次优的。据我所见,通过添加4 + 4 + 4 + 2 + 6,使用此列表可以达到的最大值是20。如果这只是背包的另一个版本,我可以实施背包解决方案,因为我可能有足够小的清单来解决这个问题,但我想做些更有效的事情。

1 个答案:

答案 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>