Knapsack
DPによって解決できる一方で、それはNP完全であることを私は知っています。彼らは、DPソリューションはpseudo-polynomial
「入力の長さ」(つまり、入力をエンコードするために必要なビット数)で指数関数的であるため、であると言います。残念ながら、私はそれを取得できませんでした。誰かpseudo-polynomial
が私にそのことをゆっくり説明できますか?
回答:
N個のアイテムとサイズWのナップサックを使用した無制限のナップサック問題の実行時間はO(NW)です。ただし、Wは入力の長さが多項式ではないため、疑似多項式になります。
W = 1,000,000,000,000を考えてみましょう。この数を表すのに40ビットしかかからないので、入力サイズ= 40ですが、計算ランタイムはO(2 40)である係数1,000,000,000,000を使用します。
したがって、ランタイムはより正確にはO(WのN.2ビット)であると言われ、これは指数関数的です。
参照:
私たちの問題のほとんどでは、標準のint / floatデータ型に快適に収まる多数の数値リストを扱っています。ほとんどのプロセッサは、追加コストなしで一度に4〜8バイトの数値を処理するように構築されているため(たとえば、1バイトに収まるよりも数値に比べて)、数値のスケールアップやスケールアップによる実行時間の変化に遭遇することはめったにありません。実際の問題で遭遇する範囲内でダウンします。したがって、支配的な要因は、データポイントの膨大な量、つまり、私たちが慣れているnまたはmの要因のままです。
(Big-O表記は、データあたり32ビットまたは64ビットを分割する定数係数を隠し、各数値がその数ビット以下に収まる場合は常にデータポイントの数のみを残すことを想像できます。 )
ただし、他のアルゴリズムを使用して、大きなint(表現するのに8バイト以上を必要とする数値)を含むデータセットを操作して、ランタイムにどのような影響があるかを確認してください。バイナリソートのような他のアルゴリズムでも、関係する数の大きさは常に違いを生みます。安全性のバッファを超えて拡張すると、従来のプロセッサは4〜8バイトのバッチを処理することで「無料」で提供します。
ここで説明したナップサックアルゴリズムの秘訣は、特定のパラメーターWの大きさに(他のアルゴリズムと比較して)異常に敏感であるということです。Wに1ビットを追加すると、アルゴリズムの実行時間が2倍になります。このアルゴリズムの前に、他のアルゴリズムの値の変化に対するそのような劇的な応答は見られませんでした。そのため、ナップザックを別の方法で扱っているように見えるかもしれませんが、それは非多項式方式でどのように応答するかについての真の分析です。入力サイズの変更に。
ナップザックアルゴリズムの実行時間は、入力のサイズ(n-アイテムの数)だけでなく、入力の大きさ(W-ナップザック容量)O(nW)にも依存します。これは、入力の大きさで指数関数的です。コンピューターでバイナリ(2 ^ n)で表されます。計算の複雑さ(つまり、コンピューター内でビットを介して処理が行われる方法)は、入力の大きさ/値ではなく、入力のサイズにのみ関係します。
値/重みリストはしばらく無視してください。ナップザック容量が2のインスタンスがあるとします。Wは入力データで2ビットを取ります。次に、ナップザックの容量を4に増やし、残りの入力を保持します。入力は1ビットしか増えていませんが、計算の複雑さは2倍になっています。容量を1024に増やすと、Wの入力は2ビットではなく10ビットになりますが、複雑さは512倍になります。時間計算量は、バイナリ(または10進数)表現のWのサイズで指数関数的に増加します。 。
疑似多項式の概念を理解するのに役立ったもう1つの簡単な例は、素数性テストアルゴリズムです。与えられた数nについて、範囲2..√nの各整数で均等に除算されているかどうかを確認しているため、アルゴリズムは√(n-1)ステップを実行します。ただし、ここで、nは入力の大きさであり、サイズではありません。
Now The regular O(n) case
対照的に、特定の要素の配列の検索は、多項式時間O(n)で実行されます。最大でnステップかかります。ここで、nは入力のサイズ(配列の長さ)です。
[ここを参照]
私がこれを理解する方法は、容量入力がサイズWの[1,2、...、W]の配列である場合、容量はO(W)であったということです。しかし、容量入力はそうではありません。数値の配列であり、代わりに単一の整数です。時間計算量は、入力のサイズとの関係に関するものです。整数のサイズは整数の値ではなく、整数を表すビット数です。後でこの整数Wをアルゴリズムで配列[1,2、...、W]に変換し、人々がWをサイズと誤解するようにしますが、この配列は入力ではなく、整数自体が入力です。
入力は「ものの配列」と考え、サイズは「配列内の物の数」と考えてください。アイテム入力は、実際には配列内のn個のアイテムの配列であるため、size = nです。容量入力は、その中のW数値の配列ではなく、 log(W)ビットの配列で表される単一の整数です。サイズを1増やし(意味のあるビットを1つ追加)、Wが2倍になるため、実行時間が2倍になるため、時間の計算量が指数関数的に複雑になります。