100672898

Page 1


* Spis treści

Przedmowa do wydania drugiego

Wst ęp

szymon acedański

Drzewo i mrówki

marcin andrychowicz

Hiperzegar

piotr chrząstowski

Piloci

Nar ciarze

marek cygan

Barykady

Biur o podróży

tomasz czajka

Grzyby po deszczu

Cu kierki

krzysztof diks

Kodowanie permutacji

Wie że

andrzej gąsienica-samek

Małpki

tomasz idziaszek

Ploter

Ter mity

grzegorz jakacki

Okno

Ołtarze

tomasz kociumaka

Osie symetrii

Lic zby Leonarda

eryk kopczyński

Rytuał

kubica

Czekolada

Sum y Fibonacciego

tomasz kulczyński

Poszukiwania

Haszowanie

jakub łącki

Herbata z mlekiem

Kangu ry

krzysztof

Super skoczek

jakub pachocki

Łyżwy

Te rmity 2

paweł parys

Jaskinia

Tas owanie

jakub pawlewicz

Gra w żetony

Pro ste

marcin pilipczuk

Gildie

Odbudow a Bajtocji

michał pilipczuk

Poligon

Zag adka

jakub radoszewski

Paliwo

Orka

wojciech rytter

Kajaki

Pr acownia malarska

krzysztof stencel

Trójkąty

Trójkąty 2

Gr a w kółko

wojciech śmietanka

Bajtocja

tomasz waleń

Klocki

jakub wojtaszczyk

Impreza

filip wolski

Dwa przyjęcia

Zga dywanka

Kodowanie permutacji

Konkurs: II Olimpiada Informatyczna

Autor zadania: Krzysztof Diks

Pamięć: 32 mb

https://oi.edu.pl/pl/archive/oi/2/kod

Każdą permutację A = (a 1, …, a n) liczb 1, …, n można zakodować za pomocą ciągu

B = (b 1, …, b n), w którym b i jest równe liczbie wszystkich a j takich, że j < i oraz a j > a i , dla każdego i = 1, …, n .

Przykład

Kodem permutacji A = (1, 5, 2, 6, 4, 7, 3) jest ciąg B = (0, 0, 1, 0, 2, 0, 4).

Zadanie

Napisz program, który:

→ wczytuje z wejścia długość n i kolejne wyrazy ciągu liczb B ,

→ sprawdza, czy jest on kodem jakiejś permutacji liczb 1, …, n ,

→ jeżeli tak, to znajduje tę permutację i zapisuje ją na wyjściu, w przeciwnym przypadku zapisuje na wyjściu jedno słowo nie.

Wejście

W pierwszym wierszu wejścia jest zapisana dodatnia liczba całkowita n ⩽ 30 000. Jest to liczba wyrazów ciągu B . W każdym z kolejnych n  wierszy jest zapisana jedna liczba całkowita nieujemna, nie większa niż 30 000. Jest to kolejny wyraz ciągu B

Wyjście

Na wyjściu należy zapisać:

→ w każdym z kolejnych n  wierszy jeden wyraz permutacji A , której kodem jest dany ciąg B , zapisany na wejściu, albo

→ jedno słowo nie, jeśli ciąg B nie jest kodem żadnej permutacji.

krzysztof diks / kodowanie permutacji

odpowiedzią jest:

Rozwiązanie

Pragnę przedstawić dwa zadania mojego autorstwa, pochodzące z zawodów Olimpiady Informatycznej. Oba zadania tylko z pozoru są bardzo łatwe. Najprostsze rozwiązanie poda natychmiast nawet początkujący algorytmik. Takie rozwiązania ad hoc okazują się jednak zbyt wolne, a prawdziwym wyzwaniem jest zaproponowanie rozwiązań znacząco szybszych.

Oba zadania dobrze ilustrują moją filozofię układania zadań dla młodych adeptów algorytmiki. Proponując zadania dla uczestników zawodów informatycznych, nie tyle myślę o tym, żeby były one oryginalne, ale żeby niosły ze sobą jakiś przekaz, np. przedstawiały techniki projektowania algorytmów, ukazywały rolę struktur danych w efektywnej implementacji algorytmów, dostarczały szablonów do rozwiązywania podobnych problemów itp. Tego typu zadaniem jest Kodowanie permutacji, które można uznać za standardowe w roku 2012, ale ma ono walory dydaktyczne, które były kluczowe w uczeniu algorytmiki w roku 1994 (brak podręczników, serwisów z zadaniami), a i dzisiaj jest ono bardzo pouczające. Podobne walory ma zadanie Wieże. Oprócz wszystkich dobrych cech zadania Kodowanie permutacji , zadanie Wieże posiada jeszcze jedną zaletę. Pozwala ono na eksperymenty (zabawę) z prawdziwą szachownicą lub z kartką papieru.

Rok 1994 był dla mnie szczególnie ważny. To rok, w którym rozpocząłem przygodę z popularyzowaniem algorytmiki wśród polskiej młodzieży – rok początku mojej pracy w Olimpiadzie Informatycznej. Praca z młodzieżą uzdolnioną informatycznie przyniosła mi, i nadal przynosi, dużo satysfakcji i wspaniałych przeżyć związanych z sukcesami młodych polskich informatyków. Miałem szczęście pracować ze zwycięzcami Międzynarodowej Olimpiady Informatycznej oraz mistrzami świata w programowaniu zespołowym. Olbrzymią radość sprawia mi obserwowanie, jak byli uczestnicy konkursów stają się znakomitymi naukowcami lub czołowymi pracownikami najlepszych firm informatycznych na świecie. A wszystko może zacząć się od próby rozwiązania zadań takich, jak te poniżej.

diks / kodowanie permutacji

/ herbata z mlekiem

Herbata z mlekiem

Konkurs: Akademickie Mistrzostwa Polski w Programowaniu Zespołowym 2011

Autor zadania: Tomasz Idziaszek

Pamięć: 32 mb https://oi.edu.pl/pl/archive/amppz/2011/her

Bajtazar podczas ostatniej wizyty na Wyspach Bitockich bardzo zasmakował w narodowym napoju Bi tocjan, którym jest herbata z mlekiem. Sposób przyrządzania i picia tego napoju jest ściśle określony i przebiega według poniższego przepisu. Najpierw napełnia się filiżankę w połowie herbatą, w połowie mlekiem i dokładnie miesza. Następnie ustala się n -literowe słowo ceremoniału złożone z liter h i m. Teraz kolejno dla i = 1, 2, …, n wykonuje się, co następuje: jeśli i -tą literą słowa ceremoniału jest h, to należy wypić połowę napoju z filiżanki, a następnie dolać do pełna herbaty i zamieszać. Jeśli zaś i -tą literą tego słowa jest m, to wykonuje się to samo, tylko zamiast herbaty dolewa się mleka. Po wykonaniu tych czynności dla każdej litery słowa ceremoniału, pozostały w filiżance napój należy wylać.

Za każdym razem, gdy Bajtazar odprawi powyżej opisaną ceremonię, zastanawia się, czy wypił więcej herbaty, czy też mleka. Pomóż Bajtazarowi w rozwikłaniu tej zagadki.

Wejście

W pierwszym wierszu wejścia znajduje się liczba całkowita n (1 ⩽ n ⩽ 100 000).

W drugim wierszu znajduje się n -literowe słowo złożone z liter h i m – jest to słowo ceremoniału, którego użył Bajtazar.

Wyjście

Twój program powinien wypisać literę h, jeśli Bajtazar wypił więcej herbaty niż mleka; literę m, jeśli wypił więcej mleka niż herbaty; lub słowo hm, jeśli wypił tyle samo herbaty co mleka.

Przykład

Dla danych wejściowych: poprawną odpowiedzią jest: 5 h hmhhm

jakub

Wyjaśnienie do przykładu: Bajtazar wypił w sumie 1 37 64 filiżanki herbaty i  59 64  filiżanki mleka.

Rozwiązanie

Gdy, na kilka tygodni przed Akademickimi Mistrzostwami Polski w Programowaniu Zespołowym, Tomasz Idziaszek przedstawił mi swój pomysł na zadanie, nie wydało mi się ono nowe. Już w szkole podstawowej lub gimnazjum, na zajęciach z matematyki zmierzyłem się z problemem Jasia, który pije mieszaninę dwóch napojów i co chwila uzupełnia swoją szklankę. Tamta wersja była jednak znacznie prostsza: Jaś uzupełniał zawartość szklanki bodaj tylko trzy razy, a po ostatniej dolewce wypijał wszystko do dna. Teraz z pewnym wstydem muszę przyznać, że wówczas pracowicie dodawałem z każdą turą coraz bardziej zawiłe ułamki, by obliczać, ile napoju trafiało za każdym razem do żołądka Jasia. Nie wpadłem na to, by po prostu obliczyć, ile napoju wlał on do szklanki…

Niewiele lepiej poradziłem sobie z zadaniem o Bajtazarze, choć tym razem wiedziałem już, że obliczanie ilości wypijanych w każdym kroku napojów nie jest najlepszym pomysłem. A już na pewno prawidłowego wyniku nie da symulacja całego procesu z wykorzystaniem typów zmiennopozycyjnych (np.  double) wbudowanych w większość języków programowania. Ich ograniczona dokładność nie pozwala na manipulowanie ułamkami, z którymi mamy do czynienia w tym zadaniu.

Jak zatem podejść do tego zadania? Sytuacja upraszcza się trochę, gdy odwrócimy postawione pytanie. Zamiast obliczać, ile herbaty i mleka wypija za każdym razem Bajtazar, zastanówmy się, jakiej części dolanych napojów nie wypije. Innymi słowy, skupmy się na obliczeniu końcowej zawartości filiżanki. Skoro wiemy, ile filiżanek każdego z napojów Bajtazar dolał w trakcie ceremonii, to te informacje wystarczą nam do udzielenia odpowiedzi. Dodatkowo, żeby uniknąć operowania na ułamkach, załóżmy, że filiżanka ma pojemność 2n + 1 mililitrów i na początku jest w niej 2n mililitrów mleka i tyleż samo herbaty.

Skupmy się na sytuacji, w której w pierwszej dolewce Bajtazar dodaje 2n  mililitrów herbaty. Zastanówmy się teraz, jak dużo tej herbaty dotrwa do samego końca ceremonii. W drugiej kolejce Bajtazar wypije połowę herbaty z tej dolewki, czyli zostanie jej 2n − 1 mililitrów; po trzeciej kolejce zostanie 2n − 2 i tak dalej. Po n kolejkach, czyli n − 1 rozcieńczeniach, w filiżance będą więc 2 mililitry pochodzące z pierwszej dolewki.

Druga dolewka będzie rozcieńczana n − 2 razy, zatem zdecyduje o 4 mililitrach ostatecznej zawartości filiżanki. Ogólnie, z i -tej dolewki dotrwa w filiżance do końca ceremonii 2i mililitrów. Oprócz tego, w filiżance pozostanie 1 mililitr herbaty oraz 1 mililitr mleka, które trafiły do niej na samym początku ceremonii.

Niech φ będzie minimalnym kątem, jaki wektor z  S tworzy z dodatnią

częścią półosi x . Niech v = (x ,y ) będzie dowolnym z wektorów, które uzyskują

ten kąt. Analogicznie definiujemy φ + i v + = (x +,y+) dla S + (patrz rys. 1). Poniższy lemat pokazuje związek pomiędzy pytaniem, na które chcemy odpowiedzieć, a sumą kątów φ i φ +

Lemat 1. Następujące trzy warunki są równoważne:

→ φ + φ + < 180°, → istnieje dodatnia liczba całkowita a , taka że wektor (a , 0) może być uzyskany jako suma wektorów ze zbioru S ∪ S +, → x + · y + x · y+ > 0.

Dowód. Mówimy, że wektor v jest nieujemną kombinacją wektorów v 1, …, v k , jeśli v = ∑k i =1 a i v i dla pewnych nieujemnych liczb rzeczywistych a i . Wprowadźmy również oznaczenie w = ( y ) · v + + y+ ·

.

y

y

Rysunek 2: Po lewej: ilustracja sytuacji dla φ + φ + ⩾ 180°, szary obszar odpowiada nieujemnym kombinacjom wektorów z S. Po prawej: ilustracja sytuacji dla φ + φ + < 180°, szary obszar odpowiada nieujemnym kombinacjom wektorów {v , v +}.

Rozważmy przypadek φ + φ + ⩾ 180° (patrz rys. 2). W tym przypadku żaden punkt na dodatniej półosi x nie jest nieujemną kombinacją wektorów z S ∪ S +

onak / superskoczek

Wszystkie nieujemne kombinacje leżą w wycinku płaszczyzny ograniczonym przez wektory v i v +, rozciągającym się od v do v + zgodnie z kierunkiem ruchu wskazówek zegara. Dlatego nie jest możliwe, aby dotrzeć na dodatnią połowę osi x przez dodawanie wektorów z  S ∪ S +. Ponadto, ponieważ wektor w jest nieujemną kombinacją v i v +, zachodzi x + · y + x · y+ ⩽ 0.

Rozważmy teraz przypadek, gdy φ + φ + < 180°. Zauważmy, że wektor w jest nieujemną kombinacją v i v + z dodatnimi całkowitymi współczynnikami, co oznacza, że wektor w może być wyrażony jako suma skończonego ciągu złożonego z wektorów v i v +. Ponieważ kąt pomiędzy v i v + nie wynosi 180° , wektory te nie są współliniowe i  w ≠ (0, 0). Co więcej, wszystkie nieujemne kombinacje v i v + znajdują się wewnątrz wycinka płaszczyzny ograniczonego przez v i  v +, rozpościerającego się zgodnie z kierunkiem ruchu wskazówek zegara od  v + do v . To oznacza, że żaden punkt na ujemnej połowie osi x nie jest nieujemną kombinacją v i v +. Zatem x + · y + x · y+, czyli pierwsza współrzędna wektora w, jest dodatnia, co kończy dowód. □

Zarówno v +, jak i  v mogą być łatwo wyznaczone w czasie liniowym. Bez utraty ogólności, ponieważ oba przypadki są symetryczne, skupmy się na wyznaczeniu v +. Rozważmy dwa wektory u = (x u , y u) i w = (x w, y w ) ze zbioru S + Kąt między u a dodatnią półosią x jest mniejszy niż kąt między w a dodatnią półosią x wtedy i tylko wtedy, gdy x u/y u > x w/y w. To wynika z własności funkcji cotangens i może być użyte do porównania pary wektorów z  S + w czasie stałym. Zgodnie z Lematem 1 wystarczy na końcu obliczyć znak wyrażenia x + · y + x · y+, aby wyznaczyć poszukiwaną odpowiedź.

Osiowa zupełność a odwracalność

Udowodnimy teraz, że jeśli S jest osiowo zupełny, to każdy ruch superskoczka można odwrócić. Ta własność jest przydatna w drugiej części naszego algorytmu, gdzie sprawdzamy zupełność zbioru osiowo zupełnego.

Lemat 2. Jeśli zbiór S je st osiowo zupełny, to jest odwracalny.

Dowód. Z definicji osiowej zupełności wynika, że istnieją wektory (a , 0), ( b, 0), (0, c ) i (0, d ), takie że a , b, c , d > 0 i każdy z nich może być wyrażony jako suma skończonego ciągu wektorów ze zbioru S . Rozważmy dowolny wektor v = (v x , v y ) z S . Wystarczy pokazać, że v może być wyrażony jako suma skończonej liczby wektorów z S . Jeśli v = (0, 0), to twierdzenie jest prawdziwe w sposób trywialny. Dlatego w pozostałej części dowodu zakładamy, że v ≠ (0, 0).

Rozważmy wektor (w x , 0), gdzie w x równa się a , jeśli v x < 0, lub b w przeciwnym przypadku. Analogicznie rozważmy wektor (0, w y ), gdzie w y równa

Niech φ będzie minimalnym kątem, jaki wektor z  S tworzy z dodatnią

częścią półosi x . Niech v = (x ,y ) będzie dowolnym z wektorów, które uzyskują

ten kąt. Analogicznie definiujemy φ + i v + = (x +,y+) dla S + (patrz rys. 1). Poniższy lemat pokazuje związek pomiędzy pytaniem, na które chcemy odpowiedzieć, a sumą kątów φ i φ +

Lemat 1. Następujące trzy warunki są równoważne:

→ φ + φ + < 180°, → istnieje dodatnia liczba całkowita a , taka że wektor (a , 0) może być uzyskany jako suma wektorów ze zbioru S ∪ S +, → x + · y + x · y+ > 0.

Dowód. Mówimy, że wektor v jest nieujemną kombinacją wektorów v 1, …, v k , jeśli v = ∑k i =1 a i v i dla pewnych nieujemnych liczb rzeczywistych a i . Wprowadźmy również oznaczenie w = ( y ) · v + + y+ ·

.

y

y

Rysunek 2: Po lewej: ilustracja sytuacji dla φ + φ + ⩾ 180°, szary obszar odpowiada nieujemnym kombinacjom wektorów z S. Po prawej: ilustracja sytuacji dla φ + φ + < 180°, szary obszar odpowiada nieujemnym kombinacjom wektorów {v , v +}.

Rozważmy przypadek φ + φ + ⩾ 180° (patrz rys. 2). W tym przypadku żaden punkt na dodatniej półosi x nie jest nieujemną kombinacją wektorów z S ∪ S +

onak / superskoczek

Wszystkie nieujemne kombinacje leżą w wycinku płaszczyzny ograniczonym przez wektory v i v +, rozciągającym się od v do v + zgodnie z kierunkiem ruchu wskazówek zegara. Dlatego nie jest możliwe, aby dotrzeć na dodatnią połowę osi x przez dodawanie wektorów z  S ∪ S +. Ponadto, ponieważ wektor w jest nieujemną kombinacją v i v +, zachodzi x + · y + x · y+ ⩽ 0.

Rozważmy teraz przypadek, gdy φ + φ + < 180°. Zauważmy, że wektor w jest nieujemną kombinacją v i v + z dodatnimi całkowitymi współczynnikami, co oznacza, że wektor w może być wyrażony jako suma skończonego ciągu złożonego z wektorów v i v +. Ponieważ kąt pomiędzy v i v + nie wynosi 180° , wektory te nie są współliniowe i  w ≠ (0, 0). Co więcej, wszystkie nieujemne kombinacje v i v + znajdują się wewnątrz wycinka płaszczyzny ograniczonego przez v i  v +, rozpościerającego się zgodnie z kierunkiem ruchu wskazówek zegara od  v + do v . To oznacza, że żaden punkt na ujemnej połowie osi x nie jest nieujemną kombinacją v i v +. Zatem x + · y + x · y+, czyli pierwsza współrzędna wektora w, jest dodatnia, co kończy dowód. □

Zarówno v +, jak i  v mogą być łatwo wyznaczone w czasie liniowym. Bez utraty ogólności, ponieważ oba przypadki są symetryczne, skupmy się na wyznaczeniu v +. Rozważmy dwa wektory u = (x u , y u) i w = (x w, y w ) ze zbioru S + Kąt między u a dodatnią półosią x jest mniejszy niż kąt między w a dodatnią półosią x wtedy i tylko wtedy, gdy x u/y u > x w/y w. To wynika z własności funkcji cotangens i może być użyte do porównania pary wektorów z  S + w czasie stałym. Zgodnie z Lematem 1 wystarczy na końcu obliczyć znak wyrażenia x + · y + x · y+, aby wyznaczyć poszukiwaną odpowiedź.

Osiowa zupełność a odwracalność

Udowodnimy teraz, że jeśli S jest osiowo zupełny, to każdy ruch superskoczka można odwrócić. Ta własność jest przydatna w drugiej części naszego algorytmu, gdzie sprawdzamy zupełność zbioru osiowo zupełnego.

Lemat 2. Jeśli zbiór S je st osiowo zupełny, to jest odwracalny.

Dowód. Z definicji osiowej zupełności wynika, że istnieją wektory (a , 0), ( b, 0), (0, c ) i (0, d ), takie że a , b, c , d > 0 i każdy z nich może być wyrażony jako suma skończonego ciągu wektorów ze zbioru S . Rozważmy dowolny wektor v = (v x , v y ) z S . Wystarczy pokazać, że v może być wyrażony jako suma skończonej liczby wektorów z S . Jeśli v = (0, 0), to twierdzenie jest prawdziwe w sposób trywialny. Dlatego w pozostałej części dowodu zakładamy, że v ≠ (0, 0).

Rozważmy wektor (w x , 0), gdzie w x równa się a , jeśli v x < 0, lub b w przeciwnym przypadku. Analogicznie rozważmy wektor (0, w y ), gdzie w y równa

Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.