Przeskocz do treści

Delta mi!

Waga

Marcin Smulewicz

o artykule ...

  • Publikacja w Delcie: czerwiec 2017
  • Publikacja elektroniczna: 31 maja 2017
  • Wersja do druku [application/pdf]: (36 KB)

W tym miesiącu omówimy zadanie Waga z finału Potyczek Algorytmicznych 2016.

Opowiada ono o dziwnej wadze Bajtazara, która wyświetla rezultat ważenia zaokrąglony do najbliższej wielokrotności |c gramów, lub błąd, gdy masa ważonych przedmiotów wynosi co najmniej k ⋅c gramów. Oprócz wagi Bajtazar posiada jeszcze n innych przedmiotów. Nie zna ich mas, więc chce je ważyć, używając swojej wagi. Nie określi on oczywiście dokładnych mas swoich przedmiotów. Jednak - być może - ważąc ich podzbiory, dla niektórych par przedmiotów będzie mógł stwierdzić, który z nich jest cięższy. I właśnie o to jesteśmy proszeni: mamy wyznaczyć liczbę takich par, mając dane dokładne masy przedmiotów.

obrazek

Przeanalizujmy, w jaki sposób Bajtazar może porównywać wagi dwóch przedmiotów. Oznaczmy ich masy przez a oraz b. Weźmy pewien podzbiór pozostałych przedmiotów o masie |x. Jeśli wskazanie wagi będzie inne w przypadku ładunku o masie a +x niż dla ładunku o masie |b+ x, to z całą pewnością można odróżnić wybrane przedmioty.

Załóżmy teraz, że naszych dwóch przedmiotów nie da się porównać w powyższy sposób. Czyli że dla każdego podzbioru pozostałych przedmiotów o masie x wskazania wagi dla mas a + x oraz b+ x będą takie same. Zauważmy ponadto, że takie samo wskazanie wagi otrzymamy dla ładunku o masie a+b |2 . Jeśli zmienimy masy obu rozpatrywanych przedmiotów na a+b -2-, to z punktu widzenia Bajtazara nic się nie zmieni! Dla każdego podzbioru przedmiotów Bajtazar otrzyma przecież dokładnie to samo wskazanie wagi zarówno przed i po takiej zmianie. Dowodzi to, że nie może on w żaden sposób rozróżnić mas tych dwóch przedmiotów, gdyż - z jego punktu widzenia - istnieje możliwość, w której ważą one dokładnie tyle samo, czyli |a+2b.

Wiemy już, w jaki sposób Bajtazar może porównywać masy przedmiotów. Do skonstruowania naszego pierwszego algorytmu rozwiązującego zadanie brakuje nam już tylko jednego prostego spostrzeżenia: jeśli wskazania wagi są różne dla ładunków o masach q i p, to będą różne również dla ładunków q − c oraz |p− c.

Aby sprawdzić, czy Bajtazar może porównać konkretne dwa przedmioty, wystarczy teraz wyznaczyć dla każdego r z przedziału |[0,c) najmniejszą masę podzbioru pozostałych przedmiotów postaci c ⋅l + r, a potem sprawdzić, czy któraś z nich jest szukanym x, rozróżniającym masy |a i b. Można zrobić to za pomocą programowania dynamicznego. Przy jego obliczaniu zaktualizowanie informacji o nowy przedmiot zajmuje czas |O(c). Sprawdzenie jednej pary przedmiotów zadziała w czasie O(c | a całe zadanie potrafimy rozwiązać w czasie O(c Złożoność ta nie jest jednak satysfakcjonująca.

Toteż musimy analizować nasz problem dalej. Ustalmy trzy takie przedmioty, że pierwszy jest nieporównywalny zarówno z drugim, jak i z trzecim. Oznaczmy ich masy odpowiednio x,y oraz z. Możemy teraz zmienić masy pierwszych dwóch przedmiotów na x+y |2 , ponieważ są one nieporównywalne i z punktu widzenia Bajtazara nic to nie zmienia. Pierwszy i trzeci przedmiot nadal są nieporównywalne i oczywiście każda inna para przedmiotów o masach x+y 2 oraz z również. Ostatecznie Bajtazar nie może rozróżnić masy drugiego i trzeciego przedmiotu. Taka własność relacji bycia nieporównywalnym jest nazywana w matematyce przechodniością. Wraz z innymi w naszym przypadku oczywistymi własnościami zwrotności i symetryczności oznacza to, że mamy do czynienia z relacją równoważności.

Abstrahując jednak od matematycznej nomenklatury, oznacza to po prostu, że przedmioty da się podzielić na rozłączne zbiory (nazywane klasami abstrakcji), takie że dwa przedmioty są nieporównywalne wtedy i tylko wtedy, gdy należą do tego samego zbioru.

Udowodnijmy ponadto, że przedmioty należące do tej samej klasy abstrakcji tworzą spójny przedział wag. Weźmy trzy przedmioty o masach |x,y oraz z, takie że |x < y < z oraz przedmioty o masach x i z są nieporównywalne. Wystarczy pokazać, że przedmiot o masie x jest nieporównywalny z przedmiotem o masie |y. Nie zmieniając instancji problemu z punktu widzenia Bajtazara, możemy zmienić masę pierwszego przedmiotu na |y, a trzeciego na |z+ x −y. Zachęcamy czytelnika do sprawdzenia, iż wskazanie wagi dla dowolnego podzbioru przedmiotów pozostanie po tej zmianie takie samo.

Możemy teraz trochę poprawić nasz algorytm. Najpierw posortujmy przedmioty ze względu na ich masy, a następnie dla każdej pary kolejnych stwierdźmy, czy są one porównywalne. Wystarcza to do wyznaczenia rozmiarów klas abstrakcji, a w szczególności również szukanej liczby par. Otrzymujemy w ten sposób algorytm działający w czasie |O(c

Jednak taka złożoność nadal nie wystarcza. Można ją poprawić, używając techniki nazywanej "Plecak bez jednego". Dla każdej pary kolejnych przedmiotów chcemy otrzymać tablicę programowania dynamicznego z dodanymi wszystkimi pozostałymi przedmiotami. Zdefiniujmy rekurencyjną procedurę  f (l,r,dp), obliczającą wyniki dla par przedmiotów o indeksach z przedziału |[l,r), mając daną tablicę programowania dynamicznego dp dla przedmiotów spoza danego przedziału. Niech m Najpierw zaktualizujmy |dp o przedmioty z przedziału [m, i wykonajmy rekurencyjnie | f dla przedziału |[l,m). Następnie pierwotne dp | zaktualizujmy o przedmioty z przedziału [l,m) i wykonajmy rekurencyjnie f dla przedziału |[m, Obliczmy również wynik dla pary przedmiotów o indeksach |m oraz m, osobno aktualizując dp | o wszystkie pozostałe przedmioty. Czas działania | f opisuje następujące równanie rekurencyjne |𝒯(l,r) = O(c . Rozwiązując je, dochodzimy do wniosku, iż złożoność czasowa naszego ostatecznego algorytmu wynosi |O(c