aktualizacja: przeczytaj o optymalizacji złożoności przestrzennej rozwiązania do programowania dynamicznego w moim kolejnym artykule tutaj.,
problem plecaka jest naprawdę interesującym problemem w kombinatoryce — aby zacytować Wikipedię,
„biorąc pod uwagę zbiór elementów, każdy z wagą i wartością, określ liczbę każdego elementu do włączenia do zbioru, tak aby całkowita waga była mniejsza lub równa danemu limitowi, a całkowita wartość była jak największa.”
z Wikipedii wynika, że istnieje kilka odmian problemu plecaka: 0-1 plecak, Ograniczony plecak i nieograniczony plecak., Dzisiaj skupimy się na najczęstszej (i najprostszej) odmianie: problem plecaka 0-1.
nieco ciekawszym i bardziej relatywnym sformułowaniem problemu plecaka 0-1 jest:
weź pod uwagę, że złodziej wchodzi do domu, aby okraść i nosi plecak. Istnieje stała liczba przedmiotów w domu-każdy z własną wagą i wartością-Biżuteria, z mniejszą wagą i najwyższą wartością vs tabele, z mniejszą wartością, ale dużo ciężkie. Aby dodać paliwo do ognia, złodziej ma Stary plecak, który ma ograniczoną pojemność., Oczywiście, nie może podzielić stołu na pół lub biżuterię na 3/4. Albo go bierze, albo zostawia. Źródło
Niestety, miałem pewne trudności ze zrozumieniem niektórych części artykułu Hackerearth, dlatego postanowiłem napisać własny artykuł. Ten artykuł będzie w dużej mierze oparty na artykule Hackerearth, a fragmenty kodu są napisane w Javie. Będę zajmował się dodatkowymi wyjaśnieniami i opracowaniami tam, gdzie uważam, że są one konieczne.
rozwiążemy ten problem przy pomocy programowania dynamicznego., Programowanie dynamiczne wymaga optymalnej podbudowy i nakładających się pod-problemów, z których oba są obecne w problemie 0-1 knapsack, jak zobaczymy.
to dobrze, jeśli nie rozumiesz, czym są „optymalna podbudowa” i „nakładające się podbudowy” (to artykuł na inny dzień). Zasadniczo oznacza to po prostu szczególny smak problemów, które pozwalają nam ponownie wykorzystać poprzednie rozwiązania mniejszych problemów w celu obliczenia rozwiązania obecnego problemu. Zaraz zobaczysz, co mam na myśli.,
szczegóły problemu
ponieważ jest to problem z plecakiem 0-1, możemy albo dołączyć element do naszego plecaka, albo go wykluczyć, ale nie dołączyć jego ułamka, albo dołączyć go wiele razy.
rozwiązanie
najpierw tworzymy 2-wymiarową tablicę (tj. tabelę)n + 1 wiersze iw + 1 kolumny.
numer wiersza i przedstawia zbiór wszystkich pozycji z wierszy 1— i. na przykład wartości w wierszu 3 zakładają, że mamy tylko pozycje 1, 2 i 3.
numer kolumny j reprezentuje nośność naszego plecaka., Dlatego wartości w kolumnie 5 zakładają na przykład, że nasz plecak może pomieścić 5 jednostek wagi.
składając wszystko razem, wpis w wierszu i, kolumnie j reprezentuje maksymalną wartość, jaką można uzyskać z pozycji 1, 2, 3 … i, w plecaku, który może pomieścić jednostki wagi j.
wywołajmy naszą tabelęmat dla macierzy. Dlatego int mat = new int.
Krok 2:
możemy natychmiast rozpocząć wypełnianie niektórych wpisów w naszej tabeli: przypadków bazowych, dla których rozwiązanie jest trywialne., Na przykład w wierszu 0, gdy nie mamy elementów do wybrania, maksymalna wartość, która może być przechowywana w dowolnym plecaku musi wynosić 0. Podobnie w kolumnie 0, dla plecaka, który może pomieścić 0 jednostek masy, maksymalna wartość, która może być w nim przechowywana, wynosi 0. (Zakładamy, że nie ma masowych, wartościowych przedmiotów.)