Programowanie dynamiczne a technika dziel i zwyciężaj

Poznaliśmy już technikę dziel i zwyciężaj. Ten e‑material poświęcony jest programowaniu dynamicznemu, który dzieli z nią kilka podobieństw, ale i różnic.

Podobieństwa:

  • Obie metody polegają na rozkładaniu większego problemu na mniejsze części, co ułatwia jego rozwiązanie.

  • Zarówno programowanie dynamiczne, jak i technika dziel i zwyciężaj często wykorzystują rekurencję do rozwiązania podproblemów.

  • Obydwie techniki są stosowane do rozwiązywania złożonych problemów, które są trudne lub niemożliwe do rozwiązania przy użyciu prostych podejść iteracyjnych.

  • Są powszechnie stosowane w algorytmice i znalazły szerokie zastosowanie w różnych dziedzinach, od optymalizacjiproblem optymalizacyjnyoptymalizacji po przetwarzanie danych.

Różnice:

  • Programowanie dynamiczne polega na rozkładaniu problemu na mniejsze podproblemy, rozwiązywaniu ich, a następnie wykorzystywaniu tych rozwiązań do rozwiązania większego problemu. Kluczowe jest tu zapamiętywanie rozwiązań podproblemów, aby uniknąć ich ponownego rozwiązywania.
    Metoda dziel i zwyciężaj polega na dzieleniu problemu na mniejsze, niezależne części, rozwiązywaniu ich oddzielnie, a następnie łączeniu wyników do uzyskania końcowego rozwiązania. Każda część jest rozwiązywana od nowa, bez wykorzystania wyników innych części.

  • Programowanie dynamiczne wymaga przechowywania wyników rozwiązanych podproblemów.
    Metoda dziel i zwyciężaj nie wymaga zazwyczaj przechowywania wyników podproblemów, ponieważ każdy podproblem jest rozwiązywany niezależnie.

  • Programowanie dynamiczne jest używane głównie w problemach optymalizacyjnych, gdzie istnieje wiele możliwych rozwiązań, a celem jest znalezienie najlepszego z nich.
    Metoda dziel i zwyciężaj jest stosowana w problemach, które naturalnie dzielą się na mniejsze części, takich jak sortowanie lub wyszukiwanie.

  • Programowanie dynamiczne jest efektywne, gdy te same podproblemy powtarzają się wielokrotnie.
    Metoda dziel i zwyciężaj jest najskuteczniejsza, gdy podproblemy są unikalne i nie powtarzają się.

Problem plecakowy – przypomnienie

Problem plecakowyproblem plecakowyProblem plecakowy polega na takim spakowaniu przedmiotów do plecaka, aby ich wartość była jak największa, a łączna waga spakowanych przedmiotów nie przekraczała pojemności plecaka. Wartość i waga każdego przedmiotu są od początku znane.

Programowanie dynamiczne to technika projektowania algorytmów polegająca na identyfikowaniu podproblemów w ramach całego problemu i rozwiązywaniu ich, zaczynając od najmniejszego. Odbywa się to dzięki memoryzacjimemoryzacjamemoryzacji - wyniki mniejszych podproblemów są zapamiętywane lub przechowywane do późniejszego wykorzystania przy rozwiązywaniu kolejnych większych podproblemów.

W przypadku problemu plecakowego mniejsze problemy odpowiadają mniejszej liczbie rodzajów pakowanych rzeczy oraz mniejszej pojemności plecaka. Rozwiązania wszystkich podproblemów można więc umieścić w tablicy.

Utwórzmy zatem tablicę, której liczba kolumn wynosi tyle, ile pojemność plecaka plus jeden (ponieważ bierzemy pod uwagę wszystkie możliwe wagi od 0 do maksymalnej pojemności), a liczba wierszy wynosi tyle, ile jest rodzajów przedmiotów plus jeden (ponieważ chcemy mieć jeden dodatkowy wiersz dla sytuacji bez przedmiotów).

Na początku wypełniamy całą tablicę zerami, ponieważ plecak jest pusty.

Zaczynamy przetwarzanie kolejnych komórek. Iterujemy przez przedmioty (wiersze), a dla każdego przedmiotu iterujemy przez wszystkie możliwe wagi (kolumny).

W liście kroków wykorzystujemy następujące zmienne:

  • i – indeks analizowanego przedmiotu;

  • poj – pojemność plecaka;

  • P – tablica przechowująca informacje o maksymalnych wartościach przedmiotów spakowanych do plecaka o danej pojemności;

  • wagi – tablica przechowująca wagi przedmiotów;

  • wartosci – tablica przechowująca wartości przedmiotów.

Dla każdej komórki tabeli wykonujemy następujące kroki:

  • Jeśli waga przedmiotu jest mniejsza lub równa pozostałej pojemności plecaka (poj):

    • Porównaj dwie wartości: wartość w komórce bez wzięcia pod uwagę tego przedmiotu, czyli P[i - 1][poj] oraz sumę wartości tego przedmiotu i wartości w komórce dla plecaka o wadze zmniejszonej o wagę tego przedmiotu, czyli P[i - 1][poj - wagi[i]] + wartości[i].

    • Wybierz większą wartość z powyższych i zapisz ją w P[i][poj].

  • Jeśli waga przedmiotu jest większa niż poj:

    • Skopiuj wartość z komórki powyżej, czyli P[i - 1][poj].

Po przejściu przez wszystkie przedmioty i wagi, wartość w komórce P[liczba przedmiotów][maksymalna waga] będzie przedstawiać maksymalną wartość, jaką można umieścić w plecaku o danej maksymalnej pojemności.

Podsumowując, każda komórka tabeli P[i][poj] reprezentuje najlepszy wynik (maksymalną wartość), który można osiągnąć dla plecaka o pojemności poj, korzystając z pierwszych i przedmiotów, gdzie każdy przedmiot może być wybrany wielokrotnie.

Na początku utworzymy tablicę, której liczba kolumn wynosi tyle, ile pojemność plecaka, a liczba wierszy wynosi tyle, ile jest rodzajów przedmiotów. Wypełnimy ją zerami. Następnie dla każdej kolejnej komórki będziemy szukać maksymalnej wartości spakowanych przedmiotów.

Przedstawimy to na przykładzie.

Przykład 1
Ważne!

Dla ułatwienia w tabeli rezygnujemy z wiersza i kolumny zerowych. Wracamy do nich w pseudokodzie.

Przedmioty i ich wagi:

Przedmiot (i)

aparat (0)

bukłak (1)

chlebak (2)

Wartość – vi

1

4

5

Waga – wi

1

2

2

Maksymalna pojemność plecaka wynosi 5.

W algorytmie dynamicznym na początku tworzymy tablicę. Wiersze tablicy reprezentują pakowane przedmioty, a kolumny – obciążenie plecaka w przedziale od 1 do 5.

Początkowo tablica P (pakowania plecaka), której będziemy używać w algorytmie dynamicznym, wygląda następująco:

1

2

3

4

5

aparat (0)

0

0

0

0

0

bukłak (1)

0

0

0

0

0

chlebak (2)

0

0

0

0

0

Wypełnimy ją

Przyjrzyjmy się kolejnym przedmiotom.

Pierwszy wiersz dotyczy aparatu, co oznacza, że próbujemy włożyć go do plecaka. Waga przedmiotu o indeksie 0 wynosi 1. Jego wartość również wynosi 1.

Zaczniemy od pojemności równej 1. Do plecaka o tej pojemności możemy spakować aparat. Zapisujemy zatem jego wartość (1) w pierwszej komórce tablicy.

Przechodzimy do pojemności równej 2. Ponownie możemy spakować aparat. Po jego spakowaniu pojemność plecaka wynosi 1. Sprawdzamy zatem (cofając się w tym samym wierszu do kolumny, która dotyczy pojemności plecaka równej 1), jaka jest maksymalna wartość przedmiotów spakowanych do plecaka o tej pojemności. To 1, zatem dodajemy ją do wartości spakowanego aparatu (również wynosi 1). W komórce wpisujemy wartość 2.

Przechodzimy do pojemności równej 3. Ponownie możemy spakować aparat. Po jego spakowaniu pojemność plecaka wynosi 2. Sprawdzamy zatem (cofając się w tym samym wierszu do kolumny, która dotyczy pojemności plecaka równej 2), jaka jest maksymalna wartość przedmiotów spakowanych do plecaka o tej pojemności. To 2, zatem dodajemy ją do wartości spakowanego właśnie aparatu (wynosi 1). W komórce wpisujemy wartość 3.

Przechodzimy do pojemności równej 4. Ponownie możemy spakować aparat. Po jego spakowaniu pojemność plecaka wynosi 3. Sprawdzamy zatem (cofając się w tym samym wierszu do kolumny, która dotyczy pojemności plecaka równej 3), jaka jest maksymalna wartość przedmiotów spakowanych do plecaka o tej pojemności. To 3, zatem dodajemy ją do wartości spakowanego właśnie aparatu (wynosi 1). W komórce wpisujemy wartość 4.

Przechodzimy do pojemności równej 5. Ponownie możemy spakować aparat. Po jego spakowaniu pojemność plecaka wynosi 4. Sprawdzamy zatem (cofając się w tym samym wierszu do kolumny, która dotyczy pojemności plecaka równej 4), jaka jest maksymalna wartość przedmiotów spakowanych do plecaka o tej pojemności. To 4, zatem dodajemy ją do wartości spakowanego właśnie aparatu (wynosi 1). W komórce wpisujemy wartość 5.

Uzupełniamy tablicę odpowiednimi wartościami.

1

2

3

4

5

aparat (0)

1

2

3

4

5

bukłak (1)

0

0

0

0

0

chlebak (2)

0

0

0

0

0

Przechodzimy do kolejnego przedmiotu, czyli bukłaka.

Pamiętaj, że w każdym wierszu rozważamy możliwość spakowania przedmiotu z danego wiersza oraz wszystkich poprzednich. Waga bukłaka wynosi 2, a jego wartość wynosi 4.

Przyjrzyjmy się kolumnie o dla pojemności równej 1. W tym momencie maksymalna wartość, którą dotychczas do niej zapakowaliśmy, jest równa 1. Rozważany przedmiot (bukłak) ma wagę równą 2, zatem nie możemy go spakować.

Maksymalna wartość dalej wynosi 1, zatem ją przepisujemy.

Sprawdzamy, czy możemy spakować bukłak do plecaka o pojemności 2. Możemy – w plecaku nie zmieści się nic więcej. Zatem w kolejnym kroku porównujemy wartość bukłaka z maksymalną wartością przedmiotów spakowanych do plecaka o tej pojemności. Jest ona większa, zatem wpisujemy ją do komórki.

1

2

3

4

5

aparat (0)

1

2

3

4

5

bukłak (1)

1

4

0

0

0

chlebak (2)

0

0

0

0

0

Przechodzimy do kolumny o indeksie 3 – taką pojemność plecaka rozważamy. Przedmiot o indeksie 1 (bukłak) może zmieścić się do plecaka. Po jego spakowaniu w plecaku zostaje miejsce na przedmiot o wadze 1. Sprawdzamy maksymalną wartość przedmiotów spakowanych do plecaka o tej pojemności. Wynosi ona 1. Sprawdźmy, czy wartość plecaka po jego spakowaniu będzie większa od dotychczasowej wartości.

Wartość jest większa, zatem w komórce zapisujemy wartość 5.

1

2

3

4

5

aparat (0)

1

2

3

4

5

bukłak (1)

1

4

5

0

0

chlebak (2)

0

0

0

0

0

Do plecaka o pojemności równej 4 również możemy zapakować bukłak. Jednak po jego zapakowaniu pojemność wynosi 2 – w plecaku jest miejsce na inny przedmiot. Cofnijmy się (w tym samym wierszu) do kolumny przeznaczonej dla pojemności plecaka równej 2. Maksymalna wartość, jaką można spakować do plecaka o pojemności 2 wynosi 4. Sprawdzamy, czy suma tych przedmiotów jest większa od dotychczas ustalonej maksymalnej wartości. Jest, zatem wpisujemy nową wartość do komórki.

1

2

3

4

5

aparat (0)

1

2

3

4

5

bukłak (1)

1

4

5

8

0

chlebak (2)

0

0

0

0

0

W przypadku plecaka o pojemności 5 ponownie możemy zapakować bukłak. Po jego spakowaniu pojemność plecaka wynosi 3. Sprawdzamy maksymalną wartość przedmiotów spakowanych do plecaka o tej pojemności. Wynosi ona 5. Suma wartości spakowanych plecaków jest większa od wcześniej osiągniętej wartości, zatem zapisujemy ją w komórce.

1

2

3

4

5

aparat (0)

1

2

3

4

5

bukłak (1)

1

4

5

8

9

chlebak (2)

0

0

0

0

0

Przechodzimy do trzeciego przedmiotu – chlebaka o indeksie 2. Jego wartość wynosi 5, a waga – 2.

Ponownie przepisujemy wartości zapisane w komórkach, które dotyczą pojemności plecaka mniejszej od wagi przedmiotu – w tym przypadku jest to tylko pojemność równa 1.

1

2

3

4

5

aparat (0)

1

2

3

4

5

bukłak (1)

1

4

5

8

9

chlebak (2)

1

0

0

0

0

Do plecaka o pojemności 2 możemy spakować 1 sztukę przedmiotu o indeksie 2 (chlebaka). Sprawdzamy, czy wartość plecaka po spakowaniu tego przedmiotu byłaby większa dla wcześniej ustalonej maksymalnej wartości dla plecaka o pojemności 2. Byłaby większa, zatem uzupełniamy komórkę wartością 5 (jest to wartość chlebaka). Przechodzimy do kolejnej komórki.

1

2

3

4

5

aparat (0)

1

2

3

4

5

bukłak (1)

1

4

5

8

9

chlebak (2)

1

5

0

0

0

Do plecaka o pojemności 3 moglibyśmy spakować przedmiot o indeksie 2. W plecaku zostałoby miejsce na przedmiot o wadze 1. Cofamy się do odpowiedniej komórki i sprawdzamy, czy wartość spakowanych przedmiotów (6) byłaby większa od wcześniej ustalonej maksymalnej wartości spakowanego plecaka o pojemności 3 (5). Byłaby, zatem wpisujemy ją do komórki.

1

2

3

4

5

aparat (0)

1

2

3

4

5

bukłak (1)

1

4

5

8

9

chlebak (2)

1

5

6

0

0

Powtarzamy działanie dla plecaka o pojemności 4. Możemy spakować do niego chlebak. Po spakowaniu chlebaka pojemność plecaka wynosi 2. Sprawdzamy, jaka jest największa możliwa wartość spakowanych przedmiotów dla plecaka o takiej pojemności. Ta wartość to 5. Sprawdzamy, czy wartość spakowanych w ten sposób przedmiotów (10) jest większa od wcześniej ustalonej maksymalnej wartości spakowanych przedmiotów dla tej pojemności plecaka (8). Jest, zatem umieszczamy ją w komórce.

1

2

3

4

5

aparat (0)

1

2

3

4

5

bukłak (1)

1

4

5

8

9

chlebak (2)

1

5

6

10

9

Powtarzamy działanie dla pojemności równej 5. Możemy spakować do niego chlebak. Po spakowaniu chlebaka pojemność plecaka wynosi 3. Sprawdzamy, jaka jest największa możliwa wartość spakowanych przedmiotów dla plecaka o takiej pojemności. Ta wartość to 6. Sprawdzamy, czy wartość spakowanych w ten sposób przedmiotów (1) jest większa od wcześniej ustalonej maksymalnej wartości spakowanych przedmiotów dla tej pojemności plecaka (9). Jest, zatem zapisujemy ją w komórce.

1

2

3

4

5

aparat (0)

1

2

3

4

5

bukłak (1)

1

4

5

8

9

chlebak (2)

1

5

6

10

11

Z tabeli możemy odczytać, że maksymalna wartość spakowanych przedmiotów dla plecaka o pojemności 5 wynosi zatem 11.

W jaki sposób odczytać z tabeli, jakie przedmioty spakowaliśmy?

Odpowiednie dane będziemy odczytywać z tabeli, w której zapisaliśmy maksymalne spakowane wartości dla plecaka o danej pojemności.

Zaczynamy od ostatniej komórki.

Sprawdzamy, czy wartość została uzyskana po spakowaniu przedmiotu o indeksie 2 (chlebaka), czy została przepisana z wiersza wyżej.

Została uzyskana po spakowaniu chlebaka do plecaka o pojemności 5. Jego waga wynosi 2. Odejmujemy ją od pojemności plecaka. Wynik to 3. Przechodzimy (w tym samym wierszu) do kolumny odpowiadającej pojemności plecaka równej 3.

Sprawdzamy, czy jej wartość została przepisana z komórki wyżej. Nie została, zatem do plecaka spakowaliśmy kolejną sztukę przedmiot o indeksie 2 (chlebaka). Jego waga to również 2, zatem odejmujemy ją od pozostałej pojemności plecaka. Wynik to 1. Przechodzimy (wciąż w tym samym wierszu) do kolumny odpowiadającej pojemności plecaka równej 1.

Wartość została przepisana z komórki wyżej, zatem do niej przechodzimy.

Ta wartość również została przepisana z komórki wyżej – przechodzimy do niej.

Nad tą komórką nie ma już innej, oznacza to, że przedmiot o indeksie 0 został spakowany do plecaka. Po jego spakoiwaniu pojemność plecaka wynosi 0. Zapełniliśmy zatem plecak przedmiotami.

Znajduje się w niej wartość, która również nie została przepisana z komórki wyżej.

W konsekwencji spakowano:

  • przedmiot o indeksie 0: 1 sztuka;

  • przedmiot o indeksie 1: 0 sztuk;

  • przedmiot o indeksie 2: 2 sztuki.

Pseudokod

Ważne!

W pseudokodzie musimy pamiętać o istnieniu kolumny oraz wiersza zerowych – dotyczą one przypadków, kiedy nie ma przedmiotów oraz pojemność plecaka wynosi 0.

Specyfikacja problemu:

Dane:

  • nazwy – tablica liczb łańcuchów znaków; nazwy poszczególnych przedmiotów

  • wartosci – tablica liczb naturalnych; wartości poszczególnych przedmiotów

  • wagi – tablica liczb naturalnych; wagi poszczególnych przedmiotów

  • poj – liczba naturalna; maksymalna pojemność plecaka

Wynik:

  • liczby sztuk poszczególnych przedmiotów (również równe 0), których całkowita waga nie przekracza wartości przechowywanej w zmiennej poj, a których całkowita wartość jest największa wśród możliwych wypełnień plecaka rzeczami o takiej wadze, która nie przekracza wartości zmiennej poj

  • całkowita wartość spakowanego plecaka

Zaczniemy od zapisania nagłówka funkcji ogolny_problem_plecakowy_dynamiczne. Przyjmuje pięć argumentów:

  • wagi – tablica liczb naturalnych; tablica wag przedmiotów;

  • wartosci – tablica liczb naturalnych; tablica wartości przedmiotów;

  • nazwy – tablica łańcuchów znaków; nazwy przedmiotów;

  • n – liczba naturalna; liczba dostępnych przedmiotów;

  • poj – liczba naturalna; pojemność plecaka.

Linia 1. Funkcja ogolny podkreślnik problem podkreślnik plecakowy podkreślnik dynamiczne otwórz nawias okrągły wagi przecinek wartosci przecinek nazwy przecinek n przecinek poj zamknij nawias okrągły dwukropek.

Tworzymy dwie tablice – P oraz Q. Długość obu tablic wynosi poj + 1, wypełniamy je zerami.

Tablica P przechowuje maksymalne wartości, jakie można osiągnąć dla różnych pojemności plecaka, a tablica Q przechowuje informacje o indeksach przedmiotów, które zostały spakowane dla danej pojemności.

Linia 1. Funkcja ogolny podkreślnik problem podkreślnik plecakowy podkreślnik dynamiczne otwórz nawias okrągły wagi przecinek wartosci przecinek nazwy przecinek n przecinek poj zamknij nawias okrągły dwukropek. Linia 2. P ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 3. Q ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły.

Zapisujemy dwie pętle dla. Pierwsza z nich iteruje przez wszystkie przedmioty, druga (zagnieżdżona) iteruje przed wszystkie możliwe pojemności plecaka.

Linia 1. Funkcja ogolny podkreślnik problem podkreślnik plecakowy podkreślnik dynamiczne otwórz nawias okrągły wagi przecinek wartosci przecinek nazwy przecinek n przecinek poj zamknij nawias okrągły dwukropek. Linia 2. P ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 3. Q ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 5. dla i znak równości 0 przecinek 1 przecinek 2 przecinek kropka kropka kropka przecinek n dwukropek. Linia 6. dla j znak równości 1 przecinek 2 przecinek 3 przecinek kropka kropka kropka przecinek poj plus 1 dwukropek.

Sprawdzamy, czy aktualnie rozważany przedmiot może być spakowany do plecaka o danej pojemności j, czyli czy jego waga jest mniejsza lub równa wartości i-tego elementu tablicy wagi.

Linia 1. Funkcja ogolny podkreślnik problem podkreślnik plecakowy podkreślnik dynamiczne otwórz nawias okrągły wagi przecinek wartosci przecinek nazwy przecinek n przecinek poj zamknij nawias okrągły dwukropek. Linia 2. P ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 3. Q ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 5. dla i znak równości 0 przecinek 1 przecinek 2 przecinek kropka kropka kropka przecinek n dwukropek. Linia 6. dla j znak równości 1 przecinek 2 przecinek 3 przecinek kropka kropka kropka przecinek poj plus 1 dwukropek. Linia 7. jeżeli wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias ostrokątny znak równości j dwukropek.

Dla każdego przedmiotu sprawdzamy, czy jego waga jest mniejsza lub równa aktualnej pojemności plecaka. Jeśli tak, to porównujemy maksymalną wartość dla aktualnej pojemności plecaka z wartością uzyskaną przez dodanie aktualnego przedmiotu. Jeśli wartość uzyskana przez dodanie przedmiotu jest większa, aktualizujemy wartość w tablicy P na pozycji j oraz indeks w tablicy Q.

Linia 1. Funkcja ogolny podkreślnik problem podkreślnik plecakowy podkreślnik dynamiczne otwórz nawias okrągły wagi przecinek wartosci przecinek nazwy przecinek n przecinek poj zamknij nawias okrągły dwukropek. Linia 2. P ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 3. Q ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 5. dla i znak równości 0 przecinek 1 przecinek 2 przecinek kropka kropka kropka przecinek n dwukropek. Linia 6. dla j znak równości 1 przecinek 2 przecinek 3 przecinek kropka kropka kropka przecinek poj plus 1 dwukropek. Linia 7. jeżeli wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias ostrokątny znak równości j dwukropek. Linia 8. jeżeli P otwórz nawias kwadratowy j zamknij nawias kwadratowy otwórz nawias ostrokątny P otwórz nawias kwadratowy j minus wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias kwadratowy plus wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy dwukropek. Linia 9. P otwórz nawias kwadratowy j zamknij nawias kwadratowy ← P otwórz nawias kwadratowy j minus wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias kwadratowy plus wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy. Linia 10. Q otwórz nawias kwadratowy j zamknij nawias kwadratowy ← i plus 1.

Tworzymy listę spakowane_przedmioty, która będzie przechowywać liczbę spakowanych sztuk każdego przedmiotu. Inicjalizujemy ją wartościami 0, ponieważ na początku jeszcze nie spakowaliśmy żadnego przedmiotu.

Inicjalizujemy zmienną pojemnosc wartością poj, czyli maksymalną pojemnością plecaka. Ta zmienna będzie nam służyć do śledzenia, ile miejsca w plecaku pozostało do zapakowania.

Uruchamiamy pętlę dopóki, która będzie wykonywać się, dopóki wartość zmiennej pojemnosc jest większa od 0, czyli w plecaku jest jeszcze miejsce.

Linia 1. Funkcja ogolny podkreślnik problem podkreślnik plecakowy podkreślnik dynamiczne otwórz nawias okrągły wagi przecinek wartosci przecinek nazwy przecinek n przecinek poj zamknij nawias okrągły dwukropek. Linia 2. P ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 3. Q ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 5. dla i znak równości 0 przecinek 1 przecinek 2 przecinek kropka kropka kropka przecinek n dwukropek. Linia 6. dla j znak równości 1 przecinek 2 przecinek 3 przecinek kropka kropka kropka przecinek poj plus 1 dwukropek. Linia 7. jeżeli wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias ostrokątny znak równości j dwukropek. Linia 8. jeżeli P otwórz nawias kwadratowy j zamknij nawias kwadratowy otwórz nawias ostrokątny P otwórz nawias kwadratowy j minus wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias kwadratowy plus wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy dwukropek. Linia 9. P otwórz nawias kwadratowy j zamknij nawias kwadratowy ← P otwórz nawias kwadratowy j minus wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias kwadratowy plus wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy. Linia 10. Q otwórz nawias kwadratowy j zamknij nawias kwadratowy ← i plus 1. Linia 12. spakowane podkreślnik przedmioty ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk n. Linia 13. pojemnosc ← poj. Linia 14. dopóki pojemnosc zamknij nawias ostrokątny 0 dwukropek.

Sprawdzamy, czy dla aktualnej pojemności pojemnosc istnieje jakiś indeks przedmiotu w tablicy Q (czyli czy został spakowany jakiś przedmiot). Jeśli tak, przechodzimy do kolejnego kroku.

Linia 1. Funkcja ogolny podkreślnik problem podkreślnik plecakowy podkreślnik dynamiczne otwórz nawias okrągły wagi przecinek wartosci przecinek nazwy przecinek n przecinek poj zamknij nawias okrągły dwukropek. Linia 2. P ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 3. Q ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 5. dla i znak równości 0 przecinek 1 przecinek 2 przecinek kropka kropka kropka przecinek n dwukropek. Linia 6. dla j znak równości 1 przecinek 2 przecinek 3 przecinek kropka kropka kropka przecinek poj plus 1 dwukropek. Linia 7. jeżeli wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias ostrokątny znak równości j dwukropek. Linia 8. jeżeli P otwórz nawias kwadratowy j zamknij nawias kwadratowy otwórz nawias ostrokątny P otwórz nawias kwadratowy j minus wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias kwadratowy plus wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy dwukropek. Linia 9. P otwórz nawias kwadratowy j zamknij nawias kwadratowy ← P otwórz nawias kwadratowy j minus wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias kwadratowy plus wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy. Linia 10. Q otwórz nawias kwadratowy j zamknij nawias kwadratowy ← i plus 1. Linia 12. spakowane podkreślnik przedmioty ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk n. Linia 13. pojemnosc ← poj. Linia 14. dopóki pojemnosc zamknij nawias ostrokątny 0 dwukropek. Linia 15. jeżeli Q otwórz nawias kwadratowy pojemnosc zamknij nawias kwadratowy wykrzyknik znak równości 0 dwukropek.

Zwiększamy licznik spakowanych sztuk dla przedmiotu o indeksie Q[pojemnosc] - 1. Indeks ten wskazuje na przedmiot, który został spakowany dla aktualnej pojemności pojemnosc.

Linia 1. Funkcja ogolny podkreślnik problem podkreślnik plecakowy podkreślnik dynamiczne otwórz nawias okrągły wagi przecinek wartosci przecinek nazwy przecinek n przecinek poj zamknij nawias okrągły dwukropek. Linia 2. P ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 3. Q ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 5. dla i znak równości 0 przecinek 1 przecinek 2 przecinek kropka kropka kropka przecinek n dwukropek. Linia 6. dla j znak równości 1 przecinek 2 przecinek 3 przecinek kropka kropka kropka przecinek poj plus 1 dwukropek. Linia 7. jeżeli wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias ostrokątny znak równości j dwukropek. Linia 8. jeżeli P otwórz nawias kwadratowy j zamknij nawias kwadratowy otwórz nawias ostrokątny P otwórz nawias kwadratowy j minus wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias kwadratowy plus wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy dwukropek. Linia 9. P otwórz nawias kwadratowy j zamknij nawias kwadratowy ← P otwórz nawias kwadratowy j minus wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias kwadratowy plus wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy. Linia 10. Q otwórz nawias kwadratowy j zamknij nawias kwadratowy ← i plus 1. Linia 12. spakowane podkreślnik przedmioty ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk n. Linia 13. pojemnosc ← poj. Linia 14. dopóki pojemnosc zamknij nawias ostrokątny 0 dwukropek. Linia 15. jeżeli Q otwórz nawias kwadratowy pojemnosc zamknij nawias kwadratowy wykrzyknik znak równości 0 dwukropek. Linia 16. spakowane podkreślnik przedmioty otwórz nawias kwadratowy Q otwórz nawias kwadratowy pojemnosc zamknij nawias kwadratowy minus 1 zamknij nawias kwadratowy plus znak równości 1.

Zmniejszamy wartość pojemnosc o wagę przedmiotu, który został spakowany dla aktualnej pojemności pojemnosc. Dzięki temu symulujemy usunięcie spakowanego przedmiotu z plecaka, aby sprawdzić, ile miejsca pozostało do zapakowania kolejnych przedmiotów.

Linia 1. Funkcja ogolny podkreślnik problem podkreślnik plecakowy podkreślnik dynamiczne otwórz nawias okrągły wagi przecinek wartosci przecinek nazwy przecinek n przecinek poj zamknij nawias okrągły dwukropek. Linia 2. P ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 3. Q ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 5. dla i znak równości 0 przecinek 1 przecinek 2 przecinek kropka kropka kropka przecinek n dwukropek. Linia 6. dla j znak równości 1 przecinek 2 przecinek 3 przecinek kropka kropka kropka przecinek poj plus 1 dwukropek. Linia 7. jeżeli wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias ostrokątny znak równości j dwukropek. Linia 8. jeżeli P otwórz nawias kwadratowy j zamknij nawias kwadratowy otwórz nawias ostrokątny P otwórz nawias kwadratowy j minus wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias kwadratowy plus wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy dwukropek. Linia 9. P otwórz nawias kwadratowy j zamknij nawias kwadratowy ← P otwórz nawias kwadratowy j minus wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias kwadratowy plus wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy. Linia 10. Q otwórz nawias kwadratowy j zamknij nawias kwadratowy ← i plus 1. Linia 12. spakowane podkreślnik przedmioty ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk n. Linia 13. pojemnosc ← poj. Linia 14. dopóki pojemnosc zamknij nawias ostrokątny 0 dwukropek. Linia 15. jeżeli Q otwórz nawias kwadratowy pojemnosc zamknij nawias kwadratowy wykrzyknik znak równości 0 dwukropek. Linia 16. spakowane podkreślnik przedmioty otwórz nawias kwadratowy Q otwórz nawias kwadratowy pojemnosc zamknij nawias kwadratowy minus 1 zamknij nawias kwadratowy plus znak równości 1. Linia 17. pojemnosc minus znak równości wagi otwórz nawias kwadratowy Q otwórz nawias kwadratowy pojemnosc zamknij nawias kwadratowy minus 1 zamknij nawias kwadratowy.

Na końcu wypisujemy informacje o spakowanych przedmiotach oraz łączną wartość spakowanych przedmiotów.

Linia 1. Funkcja ogolny podkreślnik problem podkreślnik plecakowy podkreślnik dynamiczne otwórz nawias okrągły wagi przecinek wartosci przecinek nazwy przecinek n przecinek poj zamknij nawias okrągły dwukropek. Linia 2. P ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 3. Q ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 5. dla i znak równości 0 przecinek 1 przecinek 2 przecinek kropka kropka kropka przecinek n dwukropek. Linia 6. dla j znak równości 1 przecinek 2 przecinek 3 przecinek kropka kropka kropka przecinek poj plus 1 dwukropek. Linia 7. jeżeli wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias ostrokątny znak równości j dwukropek. Linia 8. jeżeli P otwórz nawias kwadratowy j zamknij nawias kwadratowy otwórz nawias ostrokątny P otwórz nawias kwadratowy j minus wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias kwadratowy plus wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy dwukropek. Linia 9. P otwórz nawias kwadratowy j zamknij nawias kwadratowy ← P otwórz nawias kwadratowy j minus wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias kwadratowy plus wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy. Linia 10. Q otwórz nawias kwadratowy j zamknij nawias kwadratowy ← i plus 1. Linia 12. spakowane podkreślnik przedmioty ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk n. Linia 13. pojemnosc ← poj. Linia 14. dopóki pojemnosc zamknij nawias ostrokątny 0 dwukropek. Linia 15. jeżeli Q otwórz nawias kwadratowy pojemnosc zamknij nawias kwadratowy wykrzyknik znak równości 0 dwukropek. Linia 16. spakowane podkreślnik przedmioty otwórz nawias kwadratowy Q otwórz nawias kwadratowy pojemnosc zamknij nawias kwadratowy minus 1 zamknij nawias kwadratowy plus znak równości 1. Linia 17. pojemnosc minus znak równości wagi otwórz nawias kwadratowy Q otwórz nawias kwadratowy pojemnosc zamknij nawias kwadratowy minus 1 zamknij nawias kwadratowy. Linia 19. wypisz cudzysłów Liczba spakowanych sztuk przedmiotów dwukropek cudzysłów. Linia 20. dla i znak równości 0 przecinek 1 przecinek 2 przecinek kropka kropka kropka przecinek długość otwórz nawias okrągły spakowane podkreślnik przedmioty zamknij nawias okrągły dwukropek. Linia 21. wypisz nazwy otwórz nawias kwadratowy i zamknij nawias kwadratowy cudzysłów otwórz nawias okrągły indeks cudzysłów tekst otwórz nawias okrągły i zamknij nawias okrągły cudzysłów zamknij nawias okrągły cudzysłów tekst otwórz nawias okrągły spakowane podkreślnik przedmioty otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły. Linia 23. wypisz cudzysłów Wartość spakowanych przedmiotów dwukropek cudzysłów P otwórz nawias kwadratowy poj zamknij nawias kwadratowy.

Dodajemy wywołanie funkcji.

Kompletny kod:

Linia 1. Funkcja ogolny podkreślnik problem podkreślnik plecakowy podkreślnik dynamiczne otwórz nawias okrągły wagi przecinek wartosci przecinek nazwy przecinek n przecinek poj zamknij nawias okrągły dwukropek. Linia 2. P ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 3. Q ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk otwórz nawias okrągły poj plus 1 zamknij nawias okrągły. Linia 5. dla i znak równości 0 przecinek 1 przecinek 2 przecinek kropka kropka kropka przecinek n dwukropek. Linia 6. dla j znak równości 1 przecinek 2 przecinek 3 przecinek kropka kropka kropka przecinek poj plus 1 dwukropek. Linia 7. jeżeli wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias ostrokątny znak równości j dwukropek. Linia 8. jeżeli P otwórz nawias kwadratowy j zamknij nawias kwadratowy otwórz nawias ostrokątny P otwórz nawias kwadratowy j minus wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias kwadratowy plus wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy dwukropek. Linia 9. P otwórz nawias kwadratowy j zamknij nawias kwadratowy ← P otwórz nawias kwadratowy j minus wagi otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias kwadratowy plus wartosci otwórz nawias kwadratowy i zamknij nawias kwadratowy. Linia 10. Q otwórz nawias kwadratowy j zamknij nawias kwadratowy ← i plus 1. Linia 12. spakowane podkreślnik przedmioty ← otwórz nawias kwadratowy 0 zamknij nawias kwadratowy asterysk n. Linia 13. pojemnosc ← poj. Linia 14. dopóki pojemnosc zamknij nawias ostrokątny 0 dwukropek. Linia 15. jeżeli Q otwórz nawias kwadratowy pojemnosc zamknij nawias kwadratowy wykrzyknik znak równości 0 dwukropek. Linia 16. spakowane podkreślnik przedmioty otwórz nawias kwadratowy Q otwórz nawias kwadratowy pojemnosc zamknij nawias kwadratowy minus 1 zamknij nawias kwadratowy plus znak równości 1. Linia 17. pojemnosc minus znak równości wagi otwórz nawias kwadratowy Q otwórz nawias kwadratowy pojemnosc zamknij nawias kwadratowy minus 1 zamknij nawias kwadratowy. Linia 19. wypisz cudzysłów Liczba spakowanych sztuk przedmiotów dwukropek cudzysłów. Linia 20. dla i znak równości 0 przecinek 1 przecinek 2 przecinek kropka kropka kropka przecinek długość otwórz nawias okrągły spakowane podkreślnik przedmioty zamknij nawias okrągły dwukropek. Linia 21. wypisz nazwy otwórz nawias kwadratowy i zamknij nawias kwadratowy cudzysłów otwórz nawias okrągły indeks cudzysłów tekst otwórz nawias okrągły i zamknij nawias okrągły cudzysłów zamknij nawias okrągły cudzysłów tekst otwórz nawias okrągły spakowane podkreślnik przedmioty otwórz nawias kwadratowy i zamknij nawias kwadratowy zamknij nawias okrągły. Linia 23. wypisz cudzysłów Wartość spakowanych przedmiotów dwukropek cudzysłów P otwórz nawias kwadratowy poj zamknij nawias kwadratowy. Linia 25. wagi znak równości otwórz nawias kwadratowy 1 przecinek 2 przecinek 2 zamknij nawias kwadratowy. Linia 26. wartosci znak równości otwórz nawias kwadratowy 1 przecinek 4 przecinek 5 zamknij nawias kwadratowy. Linia 27. nazwy znak równości otwórz nawias kwadratowy cudzysłów aparat cudzysłów przecinek cudzysłów bukłak cudzysłów przecinek cudzysłów chlebak cudzysłów zamknij nawias kwadratowy. Linia 28. n znak równości len otwórz nawias okrągły nazwy zamknij nawias okrągły. Linia 29. poj znak równości 5. Linia 31. ogolny podkreślnik problem podkreślnik plecakowy podkreślnik dynamiczne otwórz nawias okrągły wagi przecinek wartosci przecinek nazwy przecinek n przecinek poj zamknij nawias okrągły.

Wynik działania programu:

Linia 1. Liczba spakowanych sztuk przedmiotu aparat otwórz nawias okrągły indeks 0 zamknij nawias okrągły dwukropek 1. Linia 2. Liczba spakowanych sztuk przedmiotu bukłak otwórz nawias okrągły indeks 1 zamknij nawias okrągły dwukropek 0. Linia 3. Liczba spakowanych sztuk przedmiotu chlebak otwórz nawias okrągły indeks 2 zamknij nawias okrągły dwukropek 2. Linia 4. Wartość spakowanych przedmiotów dwukropek 11.

Słownik

memoryzacja
memoryzacja

zapamiętywanie wyników mniejszych podproblemów, aby później móc z nich skorzystać przy dalszych etapach rozwiązywania większych podproblemów

problem optymalizacyjny
problem optymalizacyjny

problem obliczeniowy, którego rozwiązanie polega na znalezieniu największej lub najmniejszej wartości pewnego parametru tego problemu, spełniającej określoną własność

problem plecakowy
problem plecakowy

Problem plecakowy, który jest tematem tej serii e‑materiałów, polega na takim wyborze przedmiotów z danego zbioru, by po spakowaniu wybrane przedmioty miały jak największą wartość, ale ich waga nie przekraczała pojemności plecaka. Istnieją różne metody jego rozwiązania, w tej serii prezentujemy jedną z nich – podejście zachłanne.