0/1无背负重量背包

时间:2010-06-03 04:52:08

标签: algorithm math

考虑0/1 knapsack problem。 标准动态编程算法仅适用于填充背包的容量和权重是整数/有理数。当容量/重量不合理时你会怎么做?

问题在于我们不能像对整数权重一样进行memoize,因为我们可能需要无限权重的无限小数位 - 导致动态编程表的列数无限大。

有没有解决此问题的标准方法?对此问题的复杂性有何评论?任何启发式方法?

如(例如)相关的复发怎么样:
f(x)=1, for x< sqrt(2)

f(x)=f(x-sqrt(2))+sqrt(3),otherwise

或者Pibonacci数字问题在这里:http://www.spoj.pl/problems/PIB/

2 个答案:

答案 0 :(得分:5)

我不知道任何可以解决你所述类型问题的通用方法。也许可以使用Pibonacci中使用的记忆技术(见下面的第二部分)。

在任何情况下,有时候,我们可以通过利用下面的问题(参见sqrt(2)&amp; sqrt(3))解决方案来提供真正快速的算法。

将这些问题减少到背包可能不是一个好主意,因为我预计会有其他更快的方法。

所以回答你的问题:


涉及sqrt(2)和sqrt(3)的问题

我会先回答你的第二个问题。

f(x) = 1 for x < sqrt(2). (x >= 0 also, I presume)
f(x) = f(x-sqrt(2)) + sqrt(3)

这可以非常快速地解决(在O(log logn)时间!),仅使用整数运算(假设为O(1)),期望最后一步需要乘以sqrt(3)并加1

鉴于n,我们需要找到最小的m

n - m sqrt(2) < sqrt(2)

n - m sqrt(2) < sqrt(2) => n < (m+1)*sqrt(2) => n * sqrt(2) < m+1

n - (m-1)sqrt(2) > sqrt(2) => n > m sqrt(2) => n*sqrt(2) > m.

因此,m是n*sqrt(2)

的整数部分

我们有f(n)=(m-1)* sqrt(3)+ 1.

因此,我们只需计算[n *sqrt(2)] n*sqrt(2)的整数部分。{/ p>

这可以通过使用sqrt(2)的Continued Fractions来快速计算,它是sqrt(2)的有理逼近,并且它们在某种意义上是给定分母大小的“最佳”近似值。

可以使用递归形成sqrt(2)的连续分数a(i)/ b(i):

a0 = 1
b0 = 1
a(i+1) = a(i) +2*b(i)
b(i+1) = a(i) + b(i)

可以证明,为了近似[n * sqrt(2)],考虑一些奇数i就足够了,其中b(i)> 10 * n ^ 2(使用Liouville's approximation Theorem和连续分数的定理)和那个[n*sqrt(2)] = [n*a(i)/b(i)]

现在a(i),b(i)满足矩阵方程

[1 2] [a(i)]    [a(i+1)]
[1 1] [b(i)]  = [b(i+1)]

因此我们需要计算矩阵的幂

[1 2]
[1 1]

使条目大于10 * n ^ 2.

可以证明矩阵的所需功率是O(logn),因此可以仅使用整数运算(假设为O(1))在O(log log n)时间内计算。

因此,函数f在n处的值可以使用整数运算在O(log logn)时间内计算(最后一步除外,您需要将整数乘以sqrt(3))。


Pibonacci号码

从您的评论中,这是问题

g(x) = 1 if 0 <= x < 4
g(x) = g(x-1) + g(x-pi) x >= 4

这可以使用memoization来解决:

h(m,n) = g(m - n*pi)

然后我们有了

h(m,n) = h(m-1, n) + h(m, n+1)

所以我们有那个

g(m) = g(m-1) + h(m, 1)

现在可以通过维护两个表来使用memoization,一个用于g(m),另一个用于h(m,n)。请注意,即使你需要计算h(m,n+1),增加n只会减少m -n * pi,并且会在合理的时间内(0(m)我会在0到4之间),因此你不会继续永远。

这不像sqrt(2)和sqrt(3)解决方案那样好(或快),但我相信它确实提供了一种计算方法。


0-1具有无理系数的背包

也许对非理性进行更好和更好的理性近似,然后求解近似的0-1背包问题将最终收敛到正确的解决方案。

我的猜测是,此迭代中的固定点将为您提供解决方案。

当然,随着近似值变得越来越好,动态编程算法中的W in O(nW)很快就会变成指数,你可能会考虑所有可能性。

答案 1 :(得分:1)

作为对复杂性的快速评论,背包问题是NP-Complete(因此没有正确的多项式时间算法)。看起来,至少在直觉上,这也是NP-Complete(如果你可以正确地解决它并且无限小数位,你也可以在无限小数位全为零时解决它...即一个整数背包)。