我正在寻找以下问题的答案。
给定一组整数(无重复)和求和,找到总和为总和的集合元素的所有可能组合。解决方案顺序无关紧要(解决方案{2,2,3}和{3,2,2}相等)。
请注意,最终组合不需要是一个集合,因为它可以包含重复项。
实施例: 设置{2,3,5} 总和10
结果: {2,2,2,2,2},{2,2,3,3},{2,3,5},{5,5}
我看过Subset Sum问题以及Coin Change问题,但无法根据我的需要调整它们。我对动态编程并不熟悉,所以它可能是可行的,但是我无法理解它。
当我处理一组相当大的元素(大约50个)时,预先计算所有集合不是一个选项,因为它需要很长时间。从子集总和表中提取不同解决方案的方法将是可取的(如果可能的话)。
任何建议,提示或示例代码都将不胜感激!
答案 0 :(得分:2)
这被称为Change-making problem,是dynamic programming中的经典示例。
一些早期的答案计算了解决方案的总计计数,而问题则要求提供可能解决方案的枚举。
您还没有使用某种语言标记您的问题,因此这是Python中的一个实现。使用您的语言" bag"以适应您喜欢的任何语言。数据类型(n.b. Counter
是Python" bag")。
from collections import Counter
def ways(total, coins):
ways = [[Counter()]] + [[] for _ in range(total)]
for coin in coins:
for i in range(coin, total + 1):
ways[i] += [way + Counter({coin: 1}) for way in ways[i-coin]]
return ways[total]
输出数据类型是行李列表。用于打印它们的演示用法:
>>> from __future__ import print_function # for Python 2 compatibility
>>> for way in ways(total=10, coins=(2,3,5)):
... coins = (coin for coin,count in way.items() for _ in range(count))
... print(*coins)
...
2 2 2 2 2
2 2 3 3
2 3 5
5 5
答案 1 :(得分:0)
这是一个计算答案的Haskell函数:
partitions 0 xs = [[]]
partitions _ [] = []
partitions n (xxs@(x:xs)) | n < 0 = []
| otherwise = (map (x:) (partitions (n-x) xxs)) ++ partitions n xs
示例:
*Main> partitions 1 [1]
[[1]]
*Main> partitions 5 [1..5]
[[1,1,1,1,1],[1,1,1,2],[1,1,3],[1,2,2],[1,4],[2,3],[5]]
*Main> length $ partitions 10 [1..10]
42
*Main> length $ partitions 20 [1..20]
627
*Main> length $ partitions 40 [1..40]
37338
*Main> partitions 10 [1,2,4]
[[1,1,1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1,2],[1,1,1,1,1,1,2,2],[1,1,1,1,1,1,4],[1,1,1,1,2,2,2],[1,1,1,1,2,4],[1,1,2,2,2,2],[1,1,2,2,4],[1,1,4,4],[2,2,2,2,2],[2,2,2,4],[2,4,4]]
答案 2 :(得分:-1)
解决方案的复杂性:
其中M是sum的值,n是设置大小
int numberOfSums(Set<Integer> values, int sum) {
// sumCount[i] -> number of ways to get sum == i
int sumCount[] = new int[sum+1];
sumCount[0] = 1;
for(int v : values) {
for(int i=0; i<=sum-v; ++i)
sumCount[i+v] += sumCount[i];
}
return sumCount[sum];
}