我有一个整数数组,需要在其上应用subset sum algorithm的变体,除了找到一组总和为0的整数,我试图找到一组整数,其总和是n
。我不清楚如何使用一种标准子集和算法来适应这种变体,并且希望能够对这个问题有所了解。
答案 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 thread和this 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
- 是可用的加数(您的第二个输入)。f[x]
和true
之和,则x
为false
现在的解决方案:
最初f[0] = true
和f[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)的复杂性,因此当您输入大量数字或大量输出时,它不是非常有用。