查找以下是否存在任何可能的组合:

时间:2011-07-13 17:08:12

标签: algorithm

我获得 N 号码, n 1 n 2 n 3 n 4 ,..., n N (均为正数)。最后,我得到一个数字 K 作为输入。

我被问到是否有可能在 n 1 n 2 上找到一些可能的组合, ..., n N ,使得和等于 K ,即找到系数 a b c ,..., n ,以便:

  

a · n 1 + b · n 2 + ... + n · n N = K

其中 a b c ,..., n 可以假设从0到<的任何整数值EM>ķ

我们只需要找出是否存在这样的组合。

我一直在考虑的是限制 a b ,..., n 的极端值。例如, a 可以限制为:0≤ a ≤floor( K / a )。同样,定义 b c ,..., n 的范围。但是,在最坏的情况下,该算法最终证明是O( n n -1 )。 这个问题类似于Bin Packing问题吗? NP完整吗?

请帮我一个更好的算法(我甚至不确定我的算法是否正确!!)。

3 个答案:

答案 0 :(得分:0)

此解决方案假设数字n1,n2,... nN是整数(或者它们具有“最小公约数”)


我有一个O(K * N)算法(感谢missingno的修正)。这个想法是一点动态编程,有点像Eratosthenes的Sieve。

首先创建一个K + 1布尔列表L. L[i]如果您可以“构建”数字i(稍后会详细介绍),则属实。除false

外,L的所有值都初始化为L[0]==true

从第一个数字n1开始。对于介于1和K之间的i的每个值,请检查L[i-n1]==true是否为i-n1<0。当然,如果是L[i-n1]==false,那么就像L[i-n1]==true一样。如果L[i],则将true更改为L[n1]==true。现在,您有L[2*n1]==trueL[3*n1]==trueL[K]==true ...

L现在是什么意思? L代表[0..K]中只能用n1构建的数字。如果L[i]==false,恭喜,有一个仅使用n1构建的解决方案!

取数字n2,并做同样的事情。对于1和K之间的i的每个值,L[i-n2]==true,检查是否L[i]。如果是这种情况,则将true更改为L[K]==true

L现在是什么意思? L代表[0..K]中可以用n1和n2构建的数字。如果L[K]==false,恭喜,有一个仅使用n1和n2构建的解决方案!

如果在用所有N个值S[i]填充L之后,则无法解决您的问题。


动态编程的问题在于,一旦证明存在解决方案,检索解决方案总是一个问题......您需要另一个列表S,以便L[i]==true描述“{1}}所需的系数”建立“我。 (仅在{{1}}当然存在)

答案 1 :(得分:0)

这只是Knapsack problem的另一种变体(参见无界背包部分),并且与其他版本一样完整且硬。

当然,如果K很小,你可以使用动态编程解决方案,如果N很小,那么exasustive搜索效果也很好。

答案 2 :(得分:0)

这是一个整数程序,所以如果你有权使用求解器,我建议你描述它的性能并看看它是否适合你。