问题
There is N number of sets, each containing various number of integers, e.g.:
(-2, -1, 0), (-1,4), (-2, 2, 3), (-3, -2, 4, 6), (-2)
How to pick exactly one number from each set so that these N integers sum to zero? For example:
-1, -1, 2, -2, 4, -2
Note there might be no solution or multiple (in which case it doesn't matter which one I choose).
I was thinking that I can do breath-first search but was wondering if there are any other, preferably faster, ways to solve this.
回答1:
Let dp[i, j] = true
iff we can make sum j
using one number from each of the sets 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]
You can use a map to handle negative indexes or add an offset to make them positive. maxSum
is the maximum value your sum can take (for example sum of maximums of all sets or sum of absolute values of minimums, whichever is larger). There might be ways to update maxSum
as you go as an optimization.
For your example, this will run like so:
(-2, -1, 0), (-1,4), (-2, 2, 3), (-3, -2, 4, 6), (-2)
Iteration over the first set will give dp[1, -2] = dp[1, -1] = dp[1, 0] = true
.
Iteration over the second will give 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
) etc.
If dp[numSets, 0] = true
, there is a solution, which you can reconstruct by keeping tracking of which last number you picked for each dp[i, j]
.
The complexity is O(numSets * K * maxSum)
, where K
is the number of elements of a set. This is pseudopolynomial. It might be fast enough if your values are small. If your values are large but you have few sets with few elements, you are better off bruteforcing it using backtracking.
回答2:
This seems related to the subset sum problem: given a set n integers, is there a subset that sums to 0? That problem is known to be NP-complete and that, in short, means your chances are very small of finding a fast way of doing this.
For one set of integers it's hard enough and in your problem another constraint is added that one integer must be selected from each set. A search algorithm is indeed the way to go but in the worst case you won't be doing much better than an exhaustive search.
来源:https://stackoverflow.com/questions/9754302/choose-numbers-which-sum-to-zero