让P=[P1, P2, ..., Pk]
为k
正整数,让T
为正整数。我想生成总计最多T
的所有组合。也就是说,sum(x[i] * P[i] for i in 1:k) <= T
在组合中选择了x[i] = 1
iff i
。
实施例
允许P=[1, 2, 3]
和T=4
。组合应该是:
1
2
3
1, 2
1, 3
2, 3
因此只有组合1, 2, 3
不能存在,因为1 + 1 + 3 = 5 > 4
。
我想先生成所有组合,然后开始验证约束sum(x[i] * P[i] for i in 1:k) <= T
。但是这种方法可能比其他聪明的方法更耗时。我们如何才能产生这样的组合?
NB。如果您知道Python或Matlab中可用于生成此类组合的任何函数,则可以提供它。
谢谢。
答案 0 :(得分:3)
这就像子集求和问题(在评论中提到),除了关于找到将等于的数字加到目标上之外。您希望找到总计小于或等于到目标的数字。
尽管如此,可以使用类似的动态编程方法:
def subset_sum(vals, target=0):
sums = {0: [()]} # key=sum, value=list of subsets for the sum
if target in sums:
yield from sums[target] # annoying base case
for val in vals:
items = sums.items() # don't change dict size during iteration
sums = dict(items)
for prev_sum, prev_subsets in items:
sum_ = prev_sum + val
subsets = [s + (val,) for s in prev_subsets]
sums[sum_] = sums.get(sum_, []) + subsets
if sum_ <= target:
yield from subsets
演示:
>>> for subset in subset_sum([1, 2, 3], target=4):
... print(*subset, sep='+')
...
1
2
1+2
3
1+3