用于检查所需数个范围的数字总和的算法

时间:2011-12-26 14:19:02

标签: algorithm

我想知道下面的案例是否有更优化的算法,而不是简单地迭代项目集合。

假设有几个项目(2-10),权重定义为范围和增量,如
Item1 [0,50]增量= 5
Item2 [40,60]增量= 10。

任务是检查是否至少有一个权重组合,总计为100。 在上面的示例中,有50 + 50和40 + 60种组合。

由于物品数量不是很大,因此重复所有项目的权重不会花费太多时间,但也许有更好的方法。

由于

更新:我寻找的算法并不需要所有可能的权重或权重总和的列表,我需要算法检查是否至少有一个权重组合等于100只知道范围和增量

4 个答案:

答案 0 :(得分:1)

这个问题似乎是 subset sum problem 的一个版本,它是NP-complete。因此答案是否定的,在一般情况下可能没有有效的算法。一些 heuristics 可能会帮助您取得良好的效果。

答案 1 :(得分:1)

如果我理解这一点,我们会得到一些总T(在这种情况下T = 100),以及k对范围和间隔

([x 1 ,y 1 ],n 1 ),([x 2 ,y 2 ],n 2 ),...,([x k ,y k ],n <子>ķ

对于他们每个人我们必须选择一个值

a i ∈{x i ,x i + n i ,x i < / sub> + 2n i ,...,y i }

这样

a 1 + a 2 + ... + a k = T


所以基本上,问题是找到满足

的值c i

x 1 + c 1 n 1 + x 2 + c 2 n 2 + ... + x k + c k n k = T

受制于约束

对于所有i,

0≤c i ≤(y i -x i )/ n i

我相信这就是他们所谓的线性整数约束满足问题。这类问题的一般方法称为integer linear programming。这些问题通常是NP完全的(尽管我不知道对这个特定情况的评论差不多),但我认为仍有一些相对有效的启发式方法。

实际上,这属于一个更具体的问题子集,因为所有变量c i 只能采用有限数量的值(整数,上下限)。用于CLP(FD)的一些Google搜索(有限域上的约束逻辑编程)可能会让您了解一般如何处理这些问题(尽管如此,这可能是一个特殊情况,我不知道更简单的解决方案)。 / p>

答案 2 :(得分:0)

您可以构建一组可以生成的所有权重。高于总数的权重将被丢弃。

def weight_sum(items, total):
    possible = set([0])
    for weight_range, increment in items:
        new_possible = set(possible)
        for w in xrange(weight_range[0], weight_range[1] + 1, increment):
            new_possible.update(p + w for p in possible if p + w <= total)
        possible = new_possible
    return total in possible

items = [[[0, 50], 5], [[40, 60], 10]]
print weight_sum(items, 100)
-> True
print weight_sum(items, 111)
-> False

答案 3 :(得分:0)

Python中的暴力(我假设每个总和必须包含所有项目的权重):

from itertools import product

goal = 100
items = dict(Item1=range(0, 51, 5), Item2=range(40, 61, 10))

print(any(sum(weights) == goal for weights in product(*items.values()))) # True

product()是笛卡儿积的地方:

>>> list(product(range(1, 3+1), range(40, 60+1, 10)))
[(1, 40), (1, 50), (1, 60), (2, 40), (2, 50), (2, 60), (3, 40), (3, 50), (3, 60)]