具有非零目标总和的子集和变量

时间:2015-06-17 18:20:04

标签: c++ algorithm subset-sum

我有一个整数数组,需要在其上应用subset sum algorithm的变体,除了找到一组总和为0的整数,我试图找到一组整数,其总和是n。我不清楚如何使用一种标准子集和算法来适应这种变体,并且希望能够对这个问题有所了解。

2 个答案:

答案 0 :(得分:1)

这是subset sum problem,它是NP-Complete(没有已知的NP-Complete问题的有效解决方案),但是如果你的数字是相对较小的整数 - 有一个有效的伪多项式解决方案紧随其后:

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)

稍后,你需要退回你的选择,看看你决定“减少”的位置(取元素),以及你决定不在生成的矩阵上“减少”(不带元素)。< / p>

This threadthis thread讨论如何获取类似问题的元素。

这是一个python代码(取自我链接到的线程),可以解决这个问题。
如果你不熟悉python - 把它读成伪代码,那就很容易理解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

答案 1 :(得分:0)

您可以使用动态编程解决此问题。

让我们假设:

  • N - 是所需的总和(您的第一次输入)。
  • M - 是可用的加数(您的第二个输入)。
  • a 1 ... a M - 是可用的加数。
  • 如果您可以达到f[x]true之和,则
  • xfalse

现在的解决方案:

最初f[0] = truef[1..N] = false - 我们只能在不进行任何加数的情况下达到零的总和。

现在你可以迭代所有 i ,其中{1..M]中的i,并且每个都执行下一步操作:

f [x + a i ] = f [x + a i ] || f [x],对于[M..a i ]中的每个x - 处理顺序是相关的!

最后输出f [N]。

此解决方案具有O(N * M)的复杂性,因此当您输入大量数字或大量输出时,它不是非常有用。