Przeskocz do treści

Delta mi!

Informatyczny kącik olimpijski

Plecak

Tomasz Idziaszek

o artykule ...

  • Publikacja w Delcie: czerwiec 2013
  • Publikacja elektroniczna: 28-05-2013

Jednym z klasycznych problemów algorytmicznych jest tzw. problem plecakowy...

obrazek
obrazek

Mamy math przedmiotów i plecak o udźwigu math  W powyższym drzewie masa przedmiotu oznaczona jest liczbą kwadracików pod numerem przedmiotu, np. math zaś math

Mamy math przedmiotów i plecak o udźwigu math  W powyższym drzewie masa przedmiotu oznaczona jest liczbą kwadracików pod numerem przedmiotu, np. math zaś math

Przedstawiany jest on m.in. w następującej wersji:

Problem. Mamy math przedmiotów, ponumerowanych liczbami od math do math Każdy przedmiot ma określoną masę – math-ty przedmiot waży math  kilogramów. Mamy do dyspozycji plecak, do którego możemy zapakować przedmioty o łącznej masie co najwyżej math  kilogramów. Chcemy dowiedzieć się, jaka jest największa masa przedmiotów, które możemy zapakować do plecaka, tak by nie przekroczyć jego udźwigu.

Rozwiązanie tego problemu korzysta z metody programowania dynamicznego. Mamy tablicę math  na początku zainicjowaną wartościami math Kolejne przedmioty rozpatrujemy w kolejnych fazach algorytmu. Będziemy utrzymywali niezmiennik, że po math-tej fazie algorytmu math jeśli spośród przedmiotów ze zbioru math możemy wybrać podzbiór math o łącznej masie math Ponadto math będzie największym numerem przedmiotu, który można umieścić w pewnym math

display-math

Odpowiedzią jest, oczywiście, największe math takie że math Nasze rozwiązanie działa w czasie math  i pamięci math

W praktyce jednak, wybierając się na wycieczkę, pakujemy do plecaka rzeczy, biorąc pod uwagę ich przydatność, a nie tylko to, jak imponująco będzie wyglądał nasz plecak. W szczególności niektóre z przedmiotów są bezużyteczne, jeśli w plecaku nie znajdą się z innymi, np. wzięcie na wakacje statywu nie jest zbyt mądre, jeśli nie weźmiemy aparatu fotograficznego. I właśnie z tą ciut praktyczniejszą wersją problemu plecakowego musieli zmierzyć się uczestnicy finału Potyczek Algorytmicznych 2012. Dla każdego przedmiotu math został określony inny przedmiot math bez którego przedmiot math będzie bezużyteczny (albo math jeśli math jest przedmiotem przydatnym samym w sobie). Pytamy znów, jak ciężki plecak możemy zapakować, nie przekraczając jego udźwigu i nie zabierając żadnego bezużytecznego przedmiotu.

Zależności między przedmiotami możemy przedstawić jako drzewo: dla każdego przedmiotu math tworzymy krawędź skierowaną z węzła math do węzła math (patrz rysunek). Dodajemy także sztuczny przedmiot numer math o wadze math  Widzimy, że aby można było zapakować do plecaka przedmiot math muszą tam znaleźć się wszystkie przedmioty na ścieżce od węzła math w górę drzewa.

Okazuje się, że problem można rozwiązać całkiem prosto, ale wymaga to pewnej dozy pomysłowości i na zawodach udało się to tylko dwóm z 20 zawodników. Będziemy przeglądać przedmioty w kolejności występowania ich w drzewie w porządku preorder (czyli w kolejności przechodzenia drzewa w głąb – dla ułatwienia przenumerujmy te przedmioty, jeśli ich kolejność jest inna). Rozważamy przedmiot math i pytamy się o warunek istnienia upakowania math o masie math przedmiotami ze zbioru math jeśli bierzemy przedmiot math ale nie bierzemy żadnego bezużytecznego przedmiotu. Załóżmy, że istnieje poprawne upakowanie plecaka przedmiotami math o masie math  i że math jest największym możliwym numerem przedmiotu w  math Zauważmy, że jeśli math to w oczywisty sposób math jest poprawnym upakowaniem. Podobnie jeśli math (czyli węzeł math znajduje się w poddrzewie zaczepionym w lewym bracie węzła math), to ponieważ math  zawiera wszystkie przedmioty na ścieżce od math do korzenia, więc zawiera również przedmiot math zatem znowu bierzemy math Jeśli natomiast math to oznacza, że żadne upakowanie o masie math  nie może zawierać przedmiotu math czyli upakowanie math nie może istnieć.

Zaimplementowanie nowego rozwiązania wymaga jedynie kosmetycznej zmiany w poprzednim programie:

display-math