列出所有排列以将一些数字总结为目标数字

时间:2012-12-05 03:22:20

标签: algorithm

  

可能重复:
  Algorithm to find which number in a list sum up to a certain number

问题:

有一个列表:[1,2,3,4,6,8,10,12],我想用这些数字总结一个新的数字16。

规则:

1)不需要使用所有数字,6 + 10就可以了。

2)一个数字可以多次使用,12 + 2 + 1 + 1就可以了。

3)订单事项,12 + 6和6 + 12是两种不同的组合。

我看到algorithm to sum up a list of numbers for all combinations,但这不一样。

对算法了解不多,如果这个算法适合某些算法,请告诉我,否则会对一些python代码/伪代码表示赞赏。

1 个答案:

答案 0 :(得分:4)

首先 - 请注意,即使查找是否有任何与所需数字相加的子集为NP-Complete,也称为subset sum problem,因此没有已知的多项式解决方案。

现在,关于具体问题,以下是一些选项:

首先,当然有明显的“生成所有子集并检查总和”的方式。请注意,如果您的元素都是非负数,则可以在实际开发之前使用分支和绑定并终止大部分可能性(如果您找到了X的子集sum(X) == s,那么您正在寻找数字n < s - 您可以确定任何包含X的集合都找不到解决方案。有点像:

findSubsets(list,sol,n):
  if (list.empty() and n == 0): #found a feasible subset!
     print sol 
     return
  else if (n < 0): #bounding non feasible solutions
     return 
  else if (list.empty()): #a solution that sums to a smaller number then n
     return
  e <- list.removeAndReturnFirst()
  sol <- sol.add(e)
  findSubsets(list,sol,n-e)
  sol <- sol.removeLast()
  findSubsets(list,sol,n)
  list.addFirst(e) #cleanup, return the list to original state

使用findSubsets(list,[],n)进行调用,其中list是您的项目列表,n是所需的数字,[]是一个空列表。

请注意,如果需要,它可以很容易地并行化,在探索的两个子集之间不需要真正的同步化。


如果列表仅包含整数,则另一种方法是使用Dynamic Programming for solving the subset sum problem。获得矩阵后,您可以通过返回表格重新创建表格中的所有元素。 This similar question讨论了如何从背包DP解决方案中获取列表。这两个问题的原理几乎相同。