【问题标题】:Finding a sequence from given numbers that sum to given value?从给定数字中找到一个总和为给定值的序列?
【发布时间】:2013-10-30 02:25:23
【问题描述】:

给定一组整数(正数或负数),我怎样才能找到这些数字总和为给定值的序列?

示例:给定一个数字列表[4,-16, 9, 33],我需要总和17。我可以选择序列[4, 4, 9](数字可以重复使用)或[-16, 33]。我正在尝试找到一种有效的方法来减少序列的长度。

就像Subset Sum Problem (http://en.wikipedia.org/wiki/Subset_sum) 但在我的情况下,数字可以重复使用。

这也有点像分区问题 (Find all possible subsets that sum up to a given number),但在我的情况下是负值。

我目前的贪心算法如下。在每个循环中,我都会尝试找到一个使当前总和与目标总和之间的差异最小化的数字。

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)

【问题讨论】:

  • 看来你有办法了。您是否试图实现某种复杂性或减少要求或其他什么?
  • @WaleedKhan 这是一个贪心算法,因此它可能无法给出最佳解决方案。我希望有人能给我一个更好的解决方案,它可能更快(我的速度很慢)或给出最佳解决方案。
  • 我认为目前的算法没有考虑到所有的可能性。
  • 你需要暴力破解它......afaik没有适合这个的算法
  • @AbhishekBansal 不,它没有。它只是一个贪心算法,根据当前情况做出选择。

标签: python algorithm


【解决方案1】:

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

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

【讨论】:

  • 感谢您的建议。我会尝试Cython 来提高性能。
【解决方案2】:

由于它显然至少是 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 }

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

【讨论】:

  • 感谢您的回答。除了Integer_programming 的wiki 页面外,我不熟悉混合整数线性规划。你介意给一些适合新手的页面吗?
  • 如何证明 NP 硬度并不明显。见math.stackexchange.com/questions/12273。你有这个问题的证明草图或一些参考书目吗?
猜你喜欢
  • 1970-01-01
  • 2023-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多