我获得 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完整吗?
请帮我一个更好的算法(我甚至不确定我的算法是否正确!!)。
答案 0 :(得分:0)
此解决方案假设数字n1,n2,... nN是整数(或者它们具有“最小公约数”)
我有一个O(K * N)算法(感谢missingno的修正)。这个想法是一点动态编程,有点像Eratosthenes的Sieve。
首先创建一个K + 1布尔列表L. L[i]
如果您可以“构建”数字i(稍后会详细介绍),则属实。除false
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]==true
,L[3*n1]==true
,L[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)
这是一个整数程序,所以如果你有权使用求解器,我建议你描述它的性能并看看它是否适合你。