ナップサック問題が疑似多項式であるのはなぜですか?


90

KnapsackDPによって解決できる一方で、それはNP完全であることを私は知っています。彼らは、DPソリューションはpseudo-polynomial「入力の長さ」(つまり、入力をエンコードするために必要なビット数)で指数関数的であるため、であると言います。残念ながら、私はそれを取得できませんでした。誰かpseudo-polynomialが私にそのことをゆっくり説明できますか?


回答:


92

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ビット)であると言われ、これは指数関数的です。

参照:


1
「0-1ナップサック問題の動的計画法の複雑さ」に言及しているリンク#3は死んでいます。
dev_nut

1
申し訳ありませんが、わかりませんでした。時間計算量O(N)のアルゴリズムがある場合、指数関数的なO(2 ^(ビットインN))があるとしましょう。おかげで〜
Lushaリー

3
@LushaLiこれは私を助けました:youtube.com/watch?v = 9oI7fg-MIpE 。Nが各要素の最大サイズ入力が固定されている配列であり(たとえば、配列内の各要素が32ビット以下である場合)、この配列でforループを1回実行すると、入力の多項式時間アルゴリズムになります。配列のサイズN。ただし、Nが整数で、Nに対してループを実行する場合、Nは無制限であり、それを表すのに必要なビット数が指数関数的に増加します。したがって、Nでの単純なforループは、実際には指数関数的です。配列の場合、配列内の各要素のサイズには上限があることに注意してください。
max_max_mir

私は確信していませんでした。「疑似多項式」ではない同じプロパティを持つアルゴリズムがたくさんあります。エラトステネスのふるい(または他の素数ファインダー)の複雑さは何ですか?
OfirA.20年

31

私たちの問題のほとんどでは、標準のint / floatデータ型に快適に収まる多数の数値リストを扱っています。ほとんどのプロセッサは、追加コストなしで一度に4〜8バイトの数値を処理するように構築されているため(たとえば、1バイトに収まるよりも数値に比べて)、数値のスケールアップやスケールアップによる実行時間の変化に遭遇することはめったにありません。実際の問題で遭遇する範囲内でダウンします。したがって、支配的な要因は、データポイントの膨大な量、つまり、私たちが慣れているnまたはmの要因のままです。

(Big-O表記は、データあたり32ビットまたは64ビットを分割する定数係数を隠し、各数値がその数ビット以下に収まる場合は常にデータポイントの数のみを残すことを想像できます。 )

ただし、他のアルゴリズムを使用して、大きなint(表現するのに8バイト以上を必要とする数値)を含むデータセットを操作して、ランタイムにどのような影響があるかを確認してください。バイナリソートのような他のアルゴリズムでも、関係する数の大きさは常に違いを生みます。安全性のバッファを超えて拡張すると、従来のプロセッサは4〜8バイトのバッチを処理することで「無料」で提供します。

ここで説明したナップサックアルゴリズムの秘訣は、特定のパラメーターWの大きさに(他のアルゴリズムと比較して)異常に敏感であるということです。Wに1ビットを追加すると、アルゴリズムの実行時間が2倍になります。このアルゴリズムの前に、他のアルゴリズムの値の変化に対するそのような劇的な応答は見られませんでした。そのため、ナップザックを別の方法で扱っているように見えるかもしれませんが、それは非多項式方式でどのように応答するかについての真の分析です。入力サイズの変更に。


9

ナップザックアルゴリズムの実行時間は、入力のサイズ(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は入力のサイズ(配列の長さ)です。

[ここを参照]

10進数を格納するために必要なビットの計算


3
では、最後の検索例では、nもバイナリと見なさないのはなぜですか?n = 1024の場合、10ビットしか必要ないので、疑似多項式にするべきではありませんか?
user1024 2016年

7

私がこれを理解する方法は、容量入力サイズWの[1,2、...、W]の配列である場合、容量はO(W)であったということです。しかし、容量入力はそうではありません。数値の配列であり、代わりに単一の整数です。時間計算量は、入力のサイズとの関係に関するものです。整数のサイズは整数の値ではなく、整数を表すビット数です。後でこの整数Wをアルゴリズムで配列[1,2、...、W]に変換し、人々がWをサイズと誤解するようにしますが、この配列は入力ではなく、整数自体が入力です。

入力は「ものの配列」と考え、サイズは「配列内の物の数」と考えてください。アイテム入力は、実際には配列内のn個のアイテムの配列であるため、size = nです。容量入力はそののW数値の配列でなく、 log(W)ビットの配列で表される単一の整数です。サイズを1増やし(意味のあるビットを1つ追加)、Wが2倍になるため、実行時間が2倍になるため、時間の計算量が指数関数的に複雑になります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.