有N个集合,每个集合包含不同数量的整数,例如:
(-2, -1, 0), (-1,4), (-2, 2, 3), (-3, -2, 4, 6), (-2)
如何从每组中精确选择一个数字,使这些N个整数总和为零?例如:
-1, -1, 2, -2, 4, -2
注意可能没有解决方案或多个解决方案(在这种情况下,我选择哪一个并不重要)。
我以为我可以先进行一次呼吸搜索但是想知道是否有其他方法,最好是更快的方法来解决这个问题。
答案 0 :(得分:1)
这似乎与subset sum problem有关:给定一组 n 整数,是否有一个总和为0的子集?已知这个问题是NP-complete,简而言之,这意味着你很难找到一种快速的方法。
对于一组整数,它很难,在你的问题中,添加了另一个约束,即必须从每个集合中选择一个整数。搜索算法确实是可行的方法,但在最糟糕的情况下,您将无法比详尽的搜索做得更好。
答案 1 :(得分:1)
如果我们可以使用每个集dp[i, j] = true
中的一个数字来计算j
,请1, 2, ..., i
。
dp[i, 0] = true for all i
for i = 1 to numSets do
for num = 1 to sets[i].Count do
for j = maxSum - sets[i, num] downto -maxSum do
dp[i, j + sets[i, num]] |= dp[i - 1, j]
您可以使用地图处理负数索引或添加偏移量以使其成为正数。 maxSum
是您的总和可以采用的最大值(例如,所有集的最大值之和或最小值的绝对值之和,以较大者为准)。可能有一些方法可以在您进行优化时更新maxSum
。
对于您的示例,这将运行如下:
(-2, -1, 0), (-1,4), (-2, 2, 3), (-3, -2, 4, 6), (-2)
对第一组进行迭代将得到dp[1, -2] = dp[1, -1] = dp[1, 0] = true
。
对第二个进行迭代将给出dp[2, -3] = true (because dp[2, -2 + -1] |= dp[1, -1] = true), dp[2, -2] = true (because dp[2, -1 + -1] |= dp[1, -1] = true
)等。
如果dp[numSets, 0] = true
,则有一个解决方案,您可以通过跟踪每个dp[i, j]
选择的最后一个数字来重建。
复杂度为O(numSets * K * maxSum)
,其中K
是集合的元素数量。这是假多项式。如果你的价值很小,它可能足够快。如果你的价值很大,但你的几个元素很少,你最好用回溯来强制它。