如何找到总计最多为常数的所有组合?

时间:2017-10-25 21:56:10

标签: python algorithm matlab combinations

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中可用于生成此类组合的任何函数,则可以提供它。

谢谢。

1 个答案:

答案 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