找到一个子集的最佳近似值

问题描述

我想获得一种算法,该算法可以根据子集为我提供最佳的近似值。

这里是一个例子:

N = 45

subset = [25,10,65,9,8]

output: [25,9]

重要的一点是,算法必须给出最佳近似值(无论最终结果中元素的数量如何)。结果必须提供给出最接近的精确值(但不能超过初始值)的关联。

您知道一种算法可以用最少的时间花费吗?

非常感谢您的帮助。

解决方法

您不能在多项式时间内这样做(除非P = NP)

找出总和为N的子集显然比找到总和最接近N的子集要容易得多,这个先前的问题称为subset-sum,已知它是NP完全的。

但是,伪多项式时间是可能的。实际上,如果我们将subset中的值都当作转换为背包的权重值,则您的问题就等于0/1 knapsack optimization problem。这个0/1背包问题有一个动态编程解决方案,可以在O(nW)中运行,其中nsubset中的项数,W是目标,即{{ 1}}。

,

以下代码适用于简短列表。但是,对于较长的列表,性能会大大降低:

import itertools
def closest(my_list,my_number):
    l=[]
    for i in range(1,len(my_list)+1):
        for k in itertools.combinations(my_list,i):
            l.append([k,sum(k)])
    l=[i for i in l if i[1]<=my_number]
    l.sort(key=lambda x:x[1])
    return l[-1]
print(closest(subset,45)[0],closest(subset,45)[1])

输出:

(25,10,9) 44