-1

I have an array of integers and need to apply a variant of the subset sum algorithm on it, except that instead of finding a set of integers whose sum is 0 I am trying to find a set of integers whose sum is n. I am unclear as to how to adapt one of the standard subset sum algorithms to this variant and was hoping for any insight into the problem.

Zim-Zam O'Pootertoot
  • 17,888
  • 4
  • 41
  • 69
Kuker
  • 65
  • 3
  • 11

2 Answers2

1

This is subset sum problem, which is NP-Complete (there is no known efficient solution to NP-Complete problems), but if your numbers are relatively small integers - there is an efficient pseudo polynomial solution to it that follows the recurrence:

D(x,i) = false   x<0
D(0,i) = true
D(x,0) = false   x != 0
D(x,i) = D(x,i-1) OR D(x-arr[i],i-1)

Later, you need to step back on your choices, see where you decided to "reduce" (take the element), and where you decided not to "reduce" (not take the element), on the generated matrix.

This thread and this thread discuss how to get the elements for similar problems.

Here is a python code (taken from the thread I linked to) that does the trick.
If you are not familiar with python - read it as pseudo code, it's pretty easy to understand python!.

arr = [1,2,4,5]
n = len(arr)
SUM = 6
#pre processing:
D = [[True] * (n+1)]
for x in range(1,SUM+1):
    D.append([False]*(n+1))
#DP solution to populate D:
for x in range(1,SUM+1):
    for i in range(1,n+1):
        D[x][i] = D[x][i-1]
        if x >= arr[i-1]:
            D[x][i] = D[x][i] or D[x-arr[i-1]][i-1]
print D

#get a random solution:

if D[SUM][n] == False:
    print 'no solution'
else:
    sol = []
    x = SUM
    i = n
    while x != 0:
        possibleVals = []
        if D[x][i-1] == True:
            possibleVals.append(x)
        if x >= arr[i-1] and D[x-arr[i-1]][i-1] == True:
            possibleVals.append(x-arr[i-1])
        #by here possibleVals contains 1/2 solutions, depending on how many choices we have.
        #chose randomly one of them
        from random import randint
        r = possibleVals[randint(0,len(possibleVals)-1)]
        #if decided to add element:
        if r != x:
            sol.append(x-r)
        #modify i and x accordingly
        x = r
        i = i-1
    print sol
Community
  • 1
  • 1
amit
  • 175,853
  • 27
  • 231
  • 333
  • I really can't understand that, we can say that i'm a begginer when it come's to that advanced algorithms :) – Kuker Jun 17 '15 at 18:53
  • @Kuker See edit, I added a python code. It's pretty easy to follow python, since it's a very readable language, so you are most likely to understand the code even if you don't know python. – amit Jun 17 '15 at 19:01
  • thanks for helping. I still can't really understand python, but you gave me some ideas! It was really helpful :) – Kuker Jun 17 '15 at 19:23
0

You can solve this by using dynamic programming.

Lets assume that:

  • N - is the sum that required (your first input).
  • M - is the number of summands available (your second input).
  • a1...aM - are the summands available.
  • f[x] is true when you can reach the sum of x, and false otherwise

Now the solution:

Initially f[0] = true and f[1..N] = false - we can reach only the sum of zero without taking any summand.

Now you can iterate over all ai, where i in [1..M], and with each of them perform next operation:

f[x + ai] = f[x + ai] || f[x], for each x in [M..ai] - the order of processing is relevant!

Finally you output f[N].

This solution has the complexity of O(N*M), so it is not very useful when you either have large input numbers or large number of summands.

user3707125
  • 3,394
  • 14
  • 23
  • Thanks for answering. I won't lie, I can't understand what 'a' and 'f' stands for. What are these 'summands'? – Kuker Jun 17 '15 at 18:52
  • @Kuker, `a` or 'summands' are the "array elements" from your statement. `f` is an array I introduced to store the result over there. If you find it hard to understand - try to read some articles on "Dynamic Programming" - I learned it a while ago, so unfortunately can't suggest you any good resource. – user3707125 Jun 17 '15 at 18:59
  • I still can't get into how to implement it. This is as far as i got: `int a, b, sum, temp; vector c; while (cin >> a >> b){ for (int i = 0; i < b; i++){ cin >> temp; c.push_back(temp); } int *f = new int[a]; f[0] = true; for (int i = 1; i < b; i++){ for (int x = b; x > c[i]; x--){ f[x + c[i]] = f[x + c[i]] || f[x]; } cout << f[a];` – Kuker Jun 17 '15 at 19:21