Algorithm 如何理解背包问题是NP完全问题?

Algorithm 如何理解背包问题是NP完全问题?,algorithm,complexity-theory,Algorithm,Complexity Theory,我们知道,背包问题可以通过动态规划在O(nW)复杂度下求解。但是我们说这是一个NP完全问题。我觉得这里很难理解 (n是项目的数量,W是最大容量。)这取决于您在O(…)中放置了哪些参数 若目标权重受到数字W的限制,那个么问题就具有O(n*W)复杂性,正如您所提到的 但若权重太大,需要的算法复杂性与W无关,那个么问题就是NP完全问题。(O(2^n*n)在最简单的实现中) 要理解,你必须学习一点复杂性理论。然而,基本上,它是NP完全的,因为背包问题的一个有效算法也是,和其他问题的一个有效算法 您可以阅

我们知道,背包问题可以通过动态规划在O(nW)复杂度下求解。但是我们说这是一个NP完全问题。我觉得这里很难理解


(n是项目的数量,W是最大容量。)

这取决于您在
O(…)
中放置了哪些参数

若目标权重受到数字
W
的限制,那个么问题就具有
O(n*W)
复杂性,正如您所提到的


但若权重太大,需要的算法复杂性与
W
无关,那个么问题就是NP完全问题。(
O(2^n*n)
在最简单的实现中)

要理解,你必须学习一点复杂性理论。然而,基本上,它是NP完全的,因为背包问题的一个有效算法也是,和其他问题的一个有效算法

您可以阅读以下简短解释:。

O(n*W)
看起来像一个多项式时间,但它不是,它是

时间复杂度度量算法作为其输入的长度(以位为单位)函数的时间。动态规划解在
W
的值上确实是线性的,但在
W
的长度上却是指数的,这才是最重要的

更准确地说,背包问题动态解的时间复杂度基本上由嵌套循环给出:

// here goes other stuff we don't care about
for (i = 1 to n)
    for (j = 0 to W)
        // here goes other stuff
因此,时间复杂度显然是
O(n*W)

线性增加算法输入的大小意味着什么?这意味着使用越来越长的项目数组(因此
n
n+1
n+2
,…)和越来越长的
W
(因此,如果
W
x
位长,在一步之后我们使用
x+1
位,然后
x+2
位,…)。但是
W
的值随着
x
呈指数增长,因此该算法不是真正的多项式,而是指数(但它看起来像多项式,因此得名为“伪多项式”)


进一步参考

这是因为背包问题有一个伪多项式解,因此被称为(而不是)。

在背包0/1问题中,我们需要2个输入(1个数组和1个整数)来解决此问题:

  • n项的数组:[n1,n2,n3,…],每个项都有其值索引和权重索引
  • 整数W作为最大可接受重量

  • 假设n=10,W=8:

  • n=[n1,n2,n3,…,n10]
  • 二进制项W=1000(4位长)
  • 因此时间复杂度T(n)=O(nW)=O(10*8)=O(80)


    如果将n的大小加倍

    n=[n1,n2,n3,…n10]->n=[n1,n2,n3,…n20]

    所以时间复杂度T(n)=O(nW)=O(20*8)=O(160)


    但是,当您将W的大小增加一倍时,这并不意味着W=16,但长度将增加一倍:

    W=1000->W=10000000二进制项(8位长)

    所以T(n)=O(nW)=O(10*128)=O(1280)


    所需时间以指数形式增加,因此这是NPC问题。

    输入的大小是权重的
    log(W)
    位(对于“值”和“权重”数组,
    O(n)

    因此,权重的输入大小是
    j=log(W)
    (而不仅仅是
    W
    )。因此,
    W=2ʲ
    (使用二进制)

    最后的复杂性是
    O(n*W)

    这个
    O(n*W)
    可以重写为
    O(n*2ʲ)
    ,它与输入的大小成指数关系


    所以,这个解不是多项式。

    其他动态规划问题呢?例如,最长的公共子序列问题可以在O(L_1*L_2)时间内解决?我们能说它不是多项式吗?@cnhk看起来有多项式复杂性,O(n^2)。但是有各种各样的DP算法,例如那些处理给定集合(2^n组合)的所有子集的算法,所以我不会说每个DP问题都可以在多项式时间内解决。有两种方法可以测量数字的大小。给定数字10和1000,可以说1000是两倍大(字符数)或一百倍大。因为差异是指数的,你可以有一个算法,它是根据数值大小测量的多项式,根据位数测量的指数。我看不出编码中的位数与这个问题有任何关系。我确实理解位数如何影响整数分解的复杂性,因为单个整数是您的“输入”。然而,这里的数字
    W
    n
    表示循环迭代次数。您可以按任何方式对它们进行编码,而该循环仍将迭代
    n*W
    次。我认为这个“伪多项式”的原因是因为<代码> n>代码>是实际的输入大小,<>代码> w <代码>可以比<代码> n>代码>大得多,所以不能被公平地对待。为了帮助你理解它,1)考虑一个< <代码> > <>代码>循环,从<代码> 1 <代码>到<代码> n>代码>(其中代码< n>代码>是输入); 在这种情况下,当循环进行10^12次迭代时,输入的大小仍然在40位左右。迭代次数的增长速度快于编码输入的位数。时间复杂性不是线性的。2)再次,考虑< <代码> >循环>一个输入数组(大小为<代码> n>代码>),从<代码> 1 < /代码>到<代码> n>代码>;如果有10^12个迭代,则表示数组包含10^12个项。迭代次数的增长速度与输入的大小相同。时间比较。如果我们考虑我的例子,那么我们只需在输入中添加一个额外的位即可。有了这个,我们就完蛋了