web-dev-qa-db-ja.com

ナップザック問題がNP完全であることを理解する方法は?

ナップザック問題は、動的プログラミングによってO(nW)複雑さで解決できることがわかっています。しかし、これはNP完全問題であると言います。ここで理解するのは難しいと思います。

(nはアイテムの数です。Wは最大ボリュームです。)

70
cnhk

O(n*W)は多項式時間のように見えますが、 not であり、 pseudo-polynomial です。

時間の複雑さは、アルゴリズムが入力の長さのビットの関数としてかかる時間を測定します。ダイナミックプログラミングソリューションは確かにWの値が線形ですが、Wの長さが指数関数 —それが重要です!

より正確には、knapsack problemの動的解の時間の複雑さは、基本的にネストされたループによって与えられます。

// 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)です。

アルゴリズムの入力のサイズを線形に増やすとはどういう意味ですか?これは、次第に長いアイテム配列(nn+1n+2、...)と次第に長いWを使用することを意味します(したがって、Wxビット長である場合、1ステップ後にx+1ビット、次にx+2ビット、...)。しかし、Wvalueは、xとともに指数関数的に増加します。したがって、アルゴリズムは実際には多項式ではなく、指数関数的です(ただし、多項式のようです。


さらなる参考文献

41

ナップザック0/1問題では、この問題を解決するために2つの入力(1つの配列と1つの整数)が必要です。

  1. nアイテムの配列:[n1、n2、n3、...]、各アイテムとその値のインデックスと重みのインデックス。
  2. 整数[〜#〜] w [〜#〜]最大許容重量として

N = 10およびW = 8と仮定しましょう:

  1. n = [n1、n2、n3、...、n10]
  2. W = 2進数で1000 (4ビット長)

時間の複雑さT(n) = O(nW) = O(10 * 8)= O(80)


ダブルnのサイズの場合:

n = [n1、n2、n3、...、n1]-> n = [n1、n2、n3、...、n2]

時間の複雑さT(n) = O(nW) = O(20 * 8)= O(160)


しかしWのサイズの2倍の場合、W = 16を意味するわけではありませんが、長さは2倍長くなります。

W = 1000-> W = 2項で10000000 (8ビット長)

so T(n) = O(nW) = O(10 * 128)= O(1280)

必要な時間が指数関数的に増加するため、NPC問題です。

20
YoEugene

それはすべて、O(...)内に配置するパラメーターに依存します。

ターゲットの重みが数値Wによって制限されている場合、問題はO(n*W)複雑度になります(前述)。

しかし、重みが大きすぎて、Wに依存しない複雑さのアルゴリズムが必要な場合、問題はNP完全です。 (O(2^n*n)ほとんどの素朴な実装で)。

6
Nikita Rybak

これは、knapsack problemにはpseudo-polynomial解があるため、弱NP-Complete(および強くNP-Completeではありません)。

4
Manav Kataria

入力のサイズは、重みの場合はlog(W)ビットです(「値」および「重み」配列の場合はO(n))。

したがって、weightの入力サイズはj = log(W)(単なるWではありません)です。したがって、_W = 2ʲ_(バイナリが使用されます)。

最終的な複雑さはO(n * W)です

このO(n * W)は、入力サイズの指数関数であるO(n * 2ʲ)に書き換えることができます。

したがって、この解は多項式ではありません。

3
kaushalpranav

この短い説明を読むことができます: ナップザックのNP完全性

2
dfens

NP-completeness を理解するには、少し複雑な理論を学ぶ必要があります。ただし、ナップザック問題の効率的なアルゴリズムは [〜#〜] sat [〜#〜][〜#〜 ] tsp [〜#〜] およびその他。

0
Pontus Gagge