Informatyczny kącik olimpijski
Jeszcze dwa zadania do plecaka
W kąciku kontynuujemy przygodę z zadaniami, do których rozwiązania przydaje się znajomość problemu plecakowego. Tym razem w nieco trudniejszej jego wersji, w której każdy przedmiot ma swój rozmiar oraz wartość Standardowe pytanie, które możemy wtedy zadać, to np. jaka jest największa sumaryczna wartość przedmiotów, które możemy zapakować do plecaka, nie przekraczając jego udźwigu
Zacznijmy od zadania Meble z Obozu Naukowo-Treningowego im. A. Kreczmara z roku 2013. Chcemy urządzić mieszkanie i w tym celu zakupiliśmy rodzajów mebli do samodzielnego montażu. Mamy sztuk mebla rodzaju ; złożenie pierwszej sztuki tego rodzaju zajmie nam minut, a wraz z postępem prac będziemy nabierać wprawy i złożenie kolejnej sztuki zajmie nam o minut krócej niż poprzedniej (zakładamy, że ). Chcemy wiedzieć, ile minimalnie czasu potrzebujemy, aby złożyć dowolnych mebli.
Naturalne jest tu zastosowanie programowania dynamicznego. Jeśli oznaczymy przez minimalny czas złożenia mebli, gdy rozważamy jedynie rodzaje od 1 do to odpowiedzią będzie a rekurencją do niej prowadzącą wzór:
gdzie jest czasem montażu mebli rodzaju To rozwiązanie działa w czasie
Intuicyjnie rzecz biorąc, jeśli już zaczęliśmy składać meble danego rodzaju, to opłaca się nam wykorzystać zdobyte doświadczenie do maksimum. A formalnie: istnieje optymalne rozwiązanie, w którym mamy co najwyżej jeden rodzaj mebla którego złożymy więcej niż 0, ale mniej niż sztuk. Istotnie, załóżmy, że mamy co najmniej dwa takie nietrywialne rodzaje i których składamy odpowiednio i sztuk. Jeśli ostatni mebel rodzaju składamy nie dłużej niż ostatni mebel rodzaju to składając dodatkowe sztuk rodzaju zamiast sztuk rodzaju nie pogorszymy czasu, a zmniejszymy liczbę nietrywialnych rodzajów mebli.
Rozważmy zatem wszystkie możliwości wyboru nietrywialnego mebla Dla ustalonego pogrupujmy pozostałe rodzaje mebli w paczki o rozmiarach i czasach montażu i rozwiążmy dla nich problem plecakowy, w którym pytamy się o najmniejszą wartość przedmiotów całkowicie wypełniających plecak o udźwigu Dzięki temu w czasie dostaniemy tablicę w której oznaczać będzie minimalny czas potrzebny na złożenie dokładnie mebli, jeśli pochodzić będą z pewnej liczby w całości złożonych paczek. Zatem, dokładając do tego sztuk mebla (dla wszystkich wartości ), zmontujemy mebli w czasie Złożoność czasowa tego rozwiązania to
Zauważmy, że główny koszt algorytmu to rozwiązanie problemu plecakowego dla każdego podzbioru przedmiotów. Używając techniki, o której pisaliśmy w zeszłym miesiącu, możemy zmniejszyć złożoność czasową do
Drugie zadanie pochodzi z Wiosennego Turnieju w Programowaniu Zespołowym organizowanego przez Politechnikę Poznańską (a konkretnie z 8. edycji z roku 2004) i ma tytuł (kto by się spodziewał) Pakowanie plecaka. W zadaniu mamy plecak o udźwigu i przedmiotów, z których każdy ma swój rozmiar oraz użyteczność (przy czym niektóre przedmioty mogą być wyjątkowo nieprzydatne i mieć ujemną użyteczność). Chcemy znaleźć maksymalne upakowanie plecaka (tzn. takie, do którego nie będzie można dołożyć żadnego przedmiotu) o największej sumie użyteczności zabranych przedmiotów (zatem, być może, będziemy zmuszeni zabrać jakiś nieprzydatny przedmiot tylko po to, by dociążyć plecak).
Zauważmy, że jeśli będziemy chcieli zostawić w plecaku puste miejsce o wielkości to wszystkie przedmioty o rozmiarach nie większych niż będą musiały znaleźć się w plecaku (inaczej moglibyśmy dołożyć do plecaka co najmniej jeden z nich). Posortujmy zatem przedmioty względem ich rozmiarów i podzielmy na grupę przedmiotów "dużych" i przedmiotów "małych", co po ewentualnym przenumerowaniu przedmiotów da nam
Do plecaka na pewno weźmiemy wszystkie "małe" przedmioty o łącznym rozmiarze i użyteczności Pozostałe przedmioty muszą zająć w plecaku miejsce o wielkości dokładnie ale poza tym możemy je wybrać dowolnie. Zatem wystarczy, że rozwiążemy dla nich problem plecakowy maksymalizujący wartość zabranych przedmiotów - odpowiedzią będzie
Jeśli przeiterujemy po wartościach w kolejności malejącej, to każdy przedmiot dokładnie raz zmieni swój status z "małego" na "duży". Możemy więc na bieżąco rozwiązywać problem plecakowy i uaktualniać wartości i Wtedy koszt każdej takiej zmiany wyniesie a cały algorytm będzie miał złożoność czasową