3

Given a set of integers (positive or negative), how can I find a sequence of these numbers that sum to given value?

Example: Given a list of numbers [4,-16, 9, 33], I need the sum 17. I can choose sequence [4, 4, 9](numbers can be reused) or [-16, 33]. I'm trying to find an efficient way to reduce the length of the sequence.

It's like Subset Sum Problem (http://en.wikipedia.org/wiki/Subset_sum) but in my case numbers can be reused.

It's also a little like the Partition problem (Find all possible subsets that sum up to a given number) but in my case there's negative values.

My current greedy algorithm as follows. In each loop I'll try to find a number that minimize the difference between the current sum and target sum.

integers = [-2298478782, 1527301251, 4, 4078748803, 3388759435,
        1583071281, 2214591602, 1528349827, -12, 59460983,
        -939524100, -1, 2315255807]
target_sum = 1997393191

difference = target_sum
chain = list()
while difference != 0:
    min_abs_difference = abs(difference)
    next_int = 0
    found = False
    for i in integers:
        new_abs_diff = abs(i+difference)
        if new_abs_diff < min_abs_difference:
            found = True
            next_int = i
            min_abs_difference = new_abs_diff
    if not found:
        print(difference)
        print(chain)
        print("Cannot find an integer that makes difference smaller")
        break
    difference += next_int
    chain.append(next_int)
print(chain)
4

2 回答 2

1

由于它显然至少是 NP 完全问题,您可以将其视为混合整数线性规划问题。

Minimize summation( Xi ) // Xi = number of times the array element Ai is used.
Subject To
     summation( Ai*Xi ) = S.
     Xi >= 0 { Xi are all integers }

您可以使用任何求解器来解决它。

于 2013-10-29T18:25:23.730 回答
1

很可能没有提供最佳解决方案的快速算法。子集和问题是 NP 完全的,并且该问题比您的问题更容易(因为您允许重复使用数字)。

鉴于问题是 NP 完全的,我认为您应该专注于改进当前算法或用更快的语言(例如 C)重写它。然后您可以从 Python 调用您的 C 代码。

于 2013-10-29T18:18:11.137 回答