我需要一个针对此问题的算法:
给定一组n个自然数x1,x2,...,xn,数字S和k。形成从集合中挑选的k个数字的总和(一个数字可以多次选择)和总和S.
换句话说:列出带边界的S的每个可能组合:n <= 256,x <= 1000,k <= 32
E.g。
problem instance: {1,2,5,9,11,12,14,15}, S=30, k=3
There are 4 possible combinations
S=1+14+15, 2+14+14, 5+11+15, 9+9+12.
有了这些界限,使用蛮力是不可行的,但我认为动态编程是一种很好的方法。
该方案是:表t,其中t [m,v] =由m个数字组成的和v的组合的数量。1. Initialize t[1,x(i)], for every i.
2. Then use formula t[m,v]=Sum(t[m-1,v-x(i)], every i satisfied v-x(i)>0), 2<=m<=k.
3. After obtaining t[k,S], I can trace back to find all the combinations.
困境是t [m,v]可以通过重复的可交换组合来增加,例如,由于16 = 15 + 1和1 + 15,t [2,16] = 2。此外,最终结果f [3,30]很大,因为1 + 14 + 15,1 + 15 + 14,...,2 + 14 + 14,14 + 2 + 14,......
如何摆脱对称排列?提前谢谢。
答案 0 :(得分:2)
你可以通过对选择x元素的方式强加一个排序来摆脱排列。使您的表格成为t[m, v, n]
=来自v
的{{1}}个数组成的总和m
的三个x1..xn
=组合数。现在观察t[m, v, n] = t[m, v, n-1] + t[m-1, v-x_n, n]
。这通过仅从它们在x中的外观以相反的顺序生成加数来解决置换问题。因此,例如它将生成15 + 14 + 1和14 + 14 + 2但从未生成14 + 15 + 1。
(你可能不需要填写整个表格,所以你应该懒得计算;事实上,一个memoized递归函数可能就是你想要的。)