我不知道有什么通用方法可以解决您所述的问题。也许可以使用Pibonacci中使用的记忆化技术(请参见下面的第二节)。
无论如何,有时候,我们可以通过利用问题(参见下面的sqrt(2)和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)
的整数部分。
这可以通过使用连分数来快速计算sqrt(2),它们是对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和连分数定理),并且对于那个i,
[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(log log n)时间内计算(假设为O(1))。因此,您的函数f在n处的值可以使用仅整数算术(除了最后一步,您需要将一个整数乘以sqrt(3))在O(log logn)时间内计算。
斐波那契数列
根据您的评论,这是问题所在。
g(x) = 1 if 0 <= x < 4
g(x) = g(x-1) + g(x-pi) x >= 4
这可以通过记忆化解决:
设
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)
现在你可以通过维护两个表格来使用记忆化,一个用于g(m),另一个用于h(m,n)。请注意,即使您需要计算
h(m,n+1)
,增加n只会减少m-n*pi,并且会在合理的时间内变为0到4之间(我想是O(m)),因此您不会永远进行下去。
这不像sqrt(2)和sqrt(3)的解决方案那样好(或快),但我相信它确实提供了一种计算的方法。
0-1背包问题的非理性系数
也许对于无理数,采用越来越好的有理逼近方法,然后解决近似值的0-1背包问题,最终会收敛到正确的解决方案。
我猜测,在这个迭代中的不动点将给出你答案。
当然,随着逼近变得更好,动态规划算法中O(nW)中的W可能很快变成指数级,您最好考虑所有可能性。