考虑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/?
答案 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(如果你可以正确地解决它并且无限小数位,你也可以在无限小数位全为零时解决它...即一个整数背包)。