首先让我们将这个问题简化为整数而不是实数,否则我们将无法获得快速优化算法.例如,让我们将所有数字乘以100,然后将其四舍五入为下一个整数.所以说我们有项目大小x1,…,xn和目标大小Y.我们想要最小化该值
k1 x1 + … + kn xn – Y
在这种条件下
(1) ki is a non-positive integer for all n ≥ i ≥ 1
(2) k1 x1 + … + kn xn – Y ≥ 0
一个简单的算法就是问一系列问题
>我们能达到k1 x1 … kn xn = Y 0吗?
>我们能达到k1 x1 … kn xn = Y 1吗?
>我们能达到k1 x1 … kn xn = Y z吗?
>等随着z的增加
直到我们得到答案“是”.所有这些问题都是Knapsack问题的实例,权重设置等于项目的值.好消息是,如果我们可以为z建立上限,我们可以立即解决所有这些问题.很容易证明存在z≤Y的解,除非所有xi都大于Y,在这种情况下解决方案只是选择最小的xi.
所以让我们使用pseudopolynomial dynamic programming approach来解决背包:让f(i,j)为1,如果我们可以使用前i项(x1,…,xi)达到总项目大小j.我们已经复发了
f(0,0) = 1
f(0,j) = 0 for all j > 0
f(i,j) = f(i - 1, j) or f(i - 1, j - x_i) or f(i - 1, j - 2 * x_i) ...
我们可以在O(n * Y)时间和O(Y)空间中解决这个DP阵列.结果将是第一个j≥Y,其中f(n,j)= 1.
有一些技术细节留给读者练习:
>如何在Java中实现它>如果需要,如何重建解决方案.这可以使用DP阵列在O(n)时间内完成(但是我们需要O(n * Y)空间来记住整个事物).