背包问题为什么是伪多项式?


87

我知道这Knapsack是NP完全的,而DP可以解决。他们说DP解决方案是pseudo-polynomial,因为它在“输入长度”(即对输入进行编码所需的位数)中呈指数形式。不幸的是我没有得到。有人可以pseudo-polynomial慢慢向我解释那件事吗?


Answers:


89

对于具有N个项目且尺寸为W的背包的无界背包问题,运行时间为O(NW)。W在输入长度上不是多项式,这就是多项式的原因。

考虑W = 1,000,000,000,000。它仅用40位来表示该数字,因此输入大小= 40,但是计算运行时使用的因子为1,000,000,000,000,即O(2 40)。

因此,运行时间更准确地说是O(N.2 W),它是指数。

另请参阅:


1
指向“ 0-1背包问题的动态编程的复杂性”的链接#3无效。
dev_nut19年

1
抱歉,我没收到。假设如果我们有一个时间复杂度为O(N)的算法,那么我们就有O(2 ^(N中的位)),这是指数的吗?谢谢〜
露莎李

3
@LushaLi这对我有帮助:youtube.com/watch ? v=9oI7fg-MIpE 。如果N是一个数组,其中每个元素具有固定的最大大小输入(例如,数组中的每个元素不超过32位),并且对该数组运行一次​​for循环,则它是输入中的多项式时间算法数组的大小N。但是,如果N是一个整数,并且在N上运行一个循环,则N是无界的,并且表示它所用的位数呈指数增长。因此,在N上简单的for循环实际上是指数的。请注意,在数组的情况下,数组中每个元素的大小是上限。
max_max_mir,

我没有被说服。许多具有相同属性的算法不是“伪多项式”。说,Eratosthenes筛网(或任何其他质数查找器)的复杂性是什么?
Ofir A.

31

在大多数问题中,我们要处理大量的数字,这些数字很适合标准的int / float数据类型。由于大多数处理器的构建方式是一次可处理4-8个字节的数字而无需支付额外的费用(相对于无法容纳的数字,例如1个字节),我们很少会遇到因将数字放大或缩小而导致运行时间发生变化的情况。在实际问题中遇到的范围之内-因此,主要因素仍然只是大量的数据点,即我们习惯的n或m个因素。

(您可以想象到Big-O表示法隐藏了一个常数因子,该常数因子将每个数据分割32或64位,只要我们的每个数字都适合那么多或更少的位数,就仅保留数据点数)

但是,请尝试与其他算法配合使用,以处理涉及大整数的数据集-需要大于8个字节表示的数字-并查看对运行时有何影响。即使在诸如二进制排序之类的其他算法中,涉及到的数字的大小也总是有所不同,一旦您扩展到安全缓冲区之外,常规处理器就会通过处理4-8个字节的批处理为我们提供“免费”服务。

我们讨论过的Knapsack算法的窍门是,它对特定参数W的大小异常敏感(相对于其他算法)。向W加一位,您的算法运行时间就会增加一倍。在此之前,我们还没有见过其他算法对价值变化产生如此戏剧性的反应,这就是为什么我们似乎对Knapsack的处理方式有所不同的原因-但这是对它以非多项式方式响应的真实分析。输入大小的变化。


8

背包算法的运行时间不仅受输入大小(n-项目数)的限制,还受输入大小(W-背包容量)O(nW)的限制,O(nW)的大小呈指数关系。在计算机中以二进制(2 ^ n)表示。计算复杂性(即,如何通过位在计算机内部进行处理)仅与输入大小有关,而与它们的大小/值无关。

暂时忽略值/重量列表。假设我们有一个背包容量为2的实例。W将在输入数据中占用两位。现在,我们将背包容量增加到4,保留其余输入。我们的输入仅增加了一点,但是计算复杂度却增加了两倍。如果将容量增加到1024,则W的输入将只有10位,而不是2位,但是复杂度增加了512倍。时间复杂度以二进制(或十进制)表示的W大小呈指数增长。 。

另一个帮助我理解伪多项式概念的简单示例是朴素素性测试算法。对于给定的数字n,我们正在检查是否将其均匀除以范围2..√n中的每个整数,因此算法采用√(n-1)步。但是在这里,n是输入的大小,而不是大小。

                     Now The regular O(n) case

相反,在数组中搜索给定元素的时间为多项式时间:O(n)。它最多需要n步,这里n是输入的大小(数组的长度)。

[ 看这里 ]

计算存储十进制数所需的位


3
因此,对于您的最后一个搜索示例,为什么也不要将n也视为二进制?如果n = 1024,它也只占用10位,那么它不应该是伪多项式吗?
user1024 2016年

7

我的理解是,如果容量输入是[1,2,...,W]数组,其大小为W ,则容量将为O(W)。但是容量输入不是一个数字数组,它是一个整数。时间复杂度大约是关系尺寸输入。整数的大小不是整数的值,而是表示整数的位数。我们稍后在算法中将这个整数W转换为数组[1,2,...,W],导致人们误认为W是大小,但是这个数组不是输入,整数本身就是。

将输入视为“一组东西”,将大小视为“该阵列中有多少东西”。项输入实际上是数组中n个项的数组,因此size = n。容量输入不是其中的W数字数组而是一个由log(W)位数组表示的单个整数。将它的大小增加1(加上1个有意义的位),W增加一倍,运行时间增加一倍,因此,指数时间复杂度增加。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.