Algorithm 查找列表中要求和的最小值数

Algorithm 查找列表中要求和的最小值数,algorithm,knapsack-problem,Algorithm,Knapsack Problem,因此,如果给我一个排序列表/数组,即[1,6,8,15,40],数组的大小和请求的数字 您如何从该列表中找到所需的最小值数,以将其总和为所需的值数 例如,给定数组[1,6,8,15,40],我请求数字23,它将从列表(8和15)中取2个值来等于23。然后该函数将返回2(#个值)。此外,数组中有无限数量的1(因此您可以使用该函数始终返回一个值) 感谢您的帮助可能有一个更简单的解决方案,但如果您的列表足够短,您可以尝试每一组值,即: 1-->不是23 6-->不是23 1+6=7-->不是23

因此,如果给我一个排序列表/数组,即[1,6,8,15,40],数组的大小和请求的数字

您如何从该列表中找到所需的最小值数,以将其总和为所需的值数

例如,给定数组[1,6,8,15,40],我请求数字23,它将从列表(8和15)中取2个值来等于23。然后该函数将返回2(#个值)。此外,数组中有无限数量的1(因此您可以使用该函数始终返回一个值)


感谢您的帮助

可能有一个更简单的解决方案,但如果您的列表足够短,您可以尝试每一组值,即:

  • 1-->不是23
  • 6-->不是23
  • 1+6=7-->不是23
  • 1+8=9-->不是23
  • 1+40=41-->不是23
  • 6+8=14-->不是23
  • 8+15=23-->哦,看,是23,我们加了2个值
如果你知道你的列表已经排序,你可以跳过一些测试,因为如果6+20>23,那么就没有必要测试6+40。

NP完全简化为你的问题:给定一组整数和一个目标值s,我们为s中的每个xk构造一个值为(n+1)xk的集合s,并将目标设置为(n+1)s。如果有一个原始集合s的子集求和到s,那么在新集合中,将有一个大小不超过n的子集求和到(n+1)s,这样的集合不能包含额外的1。如果不存在这样的子集,那么作为答案生成的子集必须至少包含n+1个元素,因为它需要足够的1才能达到n+1的倍数

因此,如果没有计算革命,这个问题将不允许任何多项式时间解。有了这个免责声明,你可以考虑一些伪多项式时间的解决方案的问题,在实践中,如果最大的集合是小的。 这里有一个Python算法可以实现这一点:

import functools
S = [1, 6, 8, 15, 40] # must contain only positive integers
@functools.lru_cache(maxsize=None) # memoizing decorator
def min_subset(k, s):
    # returns the minimum size of a subset of S[:k] summing to s, including any extra 1s needed to get there
    best = s # use all ones
    for i, j in enumerate(S[:k]):
        if j <= s:
            sz = min_subset(i, s-j)+1
            if sz < best: best = sz
    return best

print min_subset(len(S), 23) # prints 2
导入工具
S=[1,6,8,15,40]#必须只包含正整数
@functools.lru_缓存(maxsize=None)#记忆装饰器
定义最小值子集(k,s):
#返回S[:k]求和到S的子集的最小大小,包括到达该子集所需的任何额外1
best=s#使用所有的
对于枚举(S[:k])中的i,j:
如果j