Ми знаємо, що проблему рюкзака можна розв’язати за складності O (nW) за допомогою динамічного програмування. Але ми говоримо, що це проблема, яка повна NP. Я відчуваю, що тут важко зрозуміти.
(n - кількість предметів. W - максимальний обсяг.)
Ми знаємо, що проблему рюкзака можна розв’язати за складності O (nW) за допомогою динамічного програмування. Але ми говоримо, що це проблема, яка повна NP. Я відчуваю, що тут важко зрозуміти.
(n - кількість предметів. W - максимальний обсяг.)
Відповіді:
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
, таким чином , алгоритм не надто Поліном, це експоненціальне (але, схоже , що поліном, звідси і назва: «псевдо-многочлен»).
W
і n
тут представляють кількість ітерацій циклу. Ви можете кодувати їх як завгодно, і цей цикл все ще буде повторюватися n * W
разів. Я вважаю, що причина цього "псевдо-полінома" полягає в тому n
, що це фактичний розмір вхідних даних, і він W
може бути набагато більшим, ніж n
це не може справедливо трактуватися як константа.
for
цикл, який йде від 1
до n
(де n
вхід); у цьому випадку, коли ваш цикл робить 10 ^ 12 ітерацій, розмір вводу все ще становить близько 40 бітів. Кількість ітерацій зростає швидше, ніж кількість бітів для кодування вхідних даних. Складність часу не є лінійною. 2) знову розглянемо for
цикл, який ітерацію над вхідним масивом (із розміром n
) від 1
до n
; якщо у вас є 10 ^ 12 ітерацій, то це означає, що ваш масив містить 10 ^ 12 елементів. Кількість ітерацій зростає з однаковим темпом, як і розмір вхідних даних. Час компл. є лінійним.
У проблемі рюкзака 0/1 нам потрібні 2 входи (1 масив і 1 ціле число) для вирішення цієї проблеми:
Припустимо, що n = 10 і W = 8:
отже, тимчасова складність 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.
Все залежить від того, які параметри ви ввели всередину O(...)
.
Якщо цільова вага обмежена кількістю W
, то проблема має O(n*W)
складність, як ви вже згадували.
Але якщо ваги занадто великі і вам потрібен алгоритм зі складністю, що не залежить від W
, тоді проблема NP-повна. ( O(2^n*n)
у більшості наївних реалізацій).
Це пояснюється тим, що проблема рюкзака має псевдополіноміальне рішення, і тому її називають слабо NP-повною (і не сильно NP-повною ).
Розмір вхідних даних - це log(W)
біти для ваги (а також O(n)
для масивів "значення" та "вага").
Отже, введений розмір ваги j = log(W)
(і не просто W
). Отже, W = 2ʲ
(як використовується двійковий файл).
Остаточна складність O(n * W)
Це
O(n * W)
можна переписати якO(n * 2ʲ)
, який експоненціально за розміром вводу.
Отже, це рішення не є поліномним.
Ви можете прочитати це коротке пояснення: NP-комплектність рюкзака .
Щоб зрозуміти NP-повноту , вам доведеться вивчити трохи теорії складності. Однак, в основному, це NP-повно, оскільки ефективний алгоритм для проблеми рюкзака також буде ефективним алгоритмом для SAT , TSP та решти.