122
Dvadsiaty druhý ročník Olympiády v informatike

Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Dvadsiaty druhý ročník

Olympiády v informatike

Page 2: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OIDvadsiaty druhý ročník Olympiády v informatikeISBN 80-8072-053-3

Page 3: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Obsah

O priebehu 22. ročníka Olympiády v informatike . . . . . . . . . . . . 3Zadania domáceho kola kategórie A . . . . . . . . . . . . . . . . . . . 5Zadania domáceho kola kategórie B . . . . . . . . . . . . . . . . . . . . 15Zadania krajského kola kategórie A . . . . . . . . . . . . . . . . . . . . 21Zadania krajského kola kategórie B . . . . . . . . . . . . . . . . . . . . 27Zadania celoštátneho kola kategórie A . . . . . . . . . . . . . . . . . . 32Riešenia domáceho kola kategórie A . . . . . . . . . . . . . . . . . . . 44Riešenia domáceho kola kategórie B . . . . . . . . . . . . . . . . . . . 63Riešenia krajského kola kategórie A . . . . . . . . . . . . . . . . . . . 68Riešenia krajského kola kategórie B . . . . . . . . . . . . . . . . . . . . 79Riešenia celoštátneho kola kategórie A . . . . . . . . . . . . . . . . . . 90Výsledky krajského kola kategórie A . . . . . . . . . . . . . . . . . . . 113Výsledky celoštátneho kola kategórie A . . . . . . . . . . . . . . . . . 116Výsledky Česko-Poľsko-Slovenského prípravného stretnutia . . . . . . 117Výsledky Medzinárodnej olympiády v informatike . . . . . . . . . . . 118Výsledky Stredoeurópskej olympiády v informatike . . . . . . . . . . . 119

Page 4: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

2

Page 5: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

O priebehu 22. ročníka Olympiády v informatike

Po dvadsaťjeden rokoch prežitých pod krídlami Matematickej olympiády sajej programátorská kategória P v školskom roku 2006/07 osamostatnila. Pred-metová olympiáda mladých programátorov tak po prvýkrát prebehla pod novouhlavičkou – Olympiáda v informatike (OI).V uvedenom školskom roku postupne začínala vznikať organizačná štruktúra

novej samostatnej súťaže. Mnoho vecí ešte prebiehalo s podporou Matematickejolympiády. Napriek rozdeleniu na dve samostatné súťaže (ktoré bolo len priro-dzeným dôsledkom toho, že skutočne ide o dve rôzne predmetové olympiády)plánujú obe olympiády aj v budúcnosti úzko spolupracovať a minimálne razročne organizovať spoločné zasadnutie komisií oboch olympiád.Na konci prvého samostatného ročníka OI ešte stále nebola oficiálne Minis-

terstvom školstva SR menovaná Slovenská komisia OI (SK OI), a súťaž tedafungovala len vďaka dobrej vôli jej zanietených organizátorov, ktorým za topatrí veľká vďaka. V čase vydania tejto ročenky už SK OI existuje a pôsobí vnasledujúcom zloženi:

• doc. RNDr. Gabriela Andrejková, CSc.,predsedkyňa, ÚI PF UPJŠ, Košice

• RNDr. Michal Forišek, podpredseda, KI FMFI UK, Bratislava• RNDr. Andrej Blaho, FMFI UK, Bratislava• Mgr. Juliana Lipková, FMFI UK, Bratislava• Bc. Ján Katrenič, PF UPJŠ, Košice• Bc. Lukáš Poláček, FMFI UK, Bratislava• PaedDr. Miloslava Sudolská, PhD.,KI FPV UMB, krajská predsedkyňa pre BB

• RNDr. Eva Hanulová, Gym. J. Hronca, krajská predsedkyňa pre BA• RNDr. Rastislav Krivoš-Belluš,Ústav informatiky PF UPJŠ, krajský predseda pre KE

• prof. Ing. Veronika Stoffová, CSc.,KI PF UJS, krajská predsedkyňa pre NR

Page 6: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

4 O priebehu 22. ročníka Olympiády v informatike

• Mgr. Mária Majherová, Ph.D.,Katedra matematiky FHPV PU, krajská predsedkyňa pre PO

• Ing. Andrea Julény, KI FMech TnUAD, krajská predsedkyňa pre TN• Mgr. Blanka Thomková, Gym. Jána Hollého, krajská predsedkyňa pre TT• RNDr. Peter Varša, Ph.D., KI FRI ŽU, krajský predseda pre ZA

Nový názov a nové logo však neboli jedinými zmenami v tomto ročníku OI.Najdôležitejšou novinkou bolo zavedenie novej kategórie B. Táto kategória je ur-čená pre žiakov, ktorí ani v školskom roku súťaže, ani v nasledujúcom školskomroku ešte nematurujú. (T.j. na klasickom štvorročnom gymnáziu je kategóriaB určená pre prvé dva ročníky.) Motiváciou pre založenie tejto kategórie bolasnaha Slovenskej komisie OI pomôcť mladším žiakom prekonať obrovskú vzdia-lenosť medzi úrovňou, na ktorej je výučba programovania na stredných školách aúrovňou, na ktorej sú úlohy kategórie A (a následných medzinárodných súťaží).Kategória B voľne zodpovedá (napr. približnou náročnosťou úloh) začiatoč-

níckej kategórii Z v Korešpondenčnom seminári z programovania (KSP) – koreš-pondenčnej súťaže, ktorej jedným z cieľov je práve dlhodobá príprava mladýcholympionikov. Paralelne s dvadsiatym druhým ročníkom OI prebehol dvadsiatyštvrtý ročník KSP.Víťazi celoštátneho kola kategórie A boli už tradične pozvaní na týždňové

výberové sústredenie, na ktorom boli vybrané štvorice reprezentantov Sloven-ska na Medzinárodnej olympiáde v informatike (IOI) v chorvátskom Záhrebe ana Stredoeurópskej olympiáde v informatike (CEOI) v Brne. Šestica riešiteľovdostala tiež príležitosť zúčastniť sa týždňového Česko-poľsko-slovenského príp-ravného sústredenia (CPSPC), ktoré sa v tomto roku konalo v Prahe. Výsledkynašich súťažiacich na týchto súťažiach nájdete na konci ročenky.Priebeh Olympiády v informatike samozrejme zahŕňa obetavú prácu mno-

hých ľudí, ktorí sa na jej chode podieľajú v jednotlivých krajoch, na školách,na krajských školských úradoch a centrách voľného času. . . Bez týchto ľudí bynaša olympiáda nemohla fungovať a aspoň touto cestou im všetkým ďakujeme adúfame, že aspoň rovnako dobre bude naša spolupráca fungovať aj v budúcnosti.

Michal Forišek, podpredseda SK OI

Page 7: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania domáceho kola kategórie A

A-I-1 Rozvoz pizze

Marcove dve životné lásky boli kulinárstvo a cyklistika. A ako to tak chodí,jedného dňa prišiel na to, že môže obe uplatniť na svoju obživu, a založil si firmuna výrobu a rozvoz pizze. Plánuje ju prevádzkovať tak, že vždy najskôr nazbieraobjednávky, a keď ich už bude mať dosť, napečie pizzu, sadne na bicykel a pôjdeju rozvážať.Marco zatiaľ vie piecť len jediný druh pizze. Keďže si ale uvedomil, že tým

konkurenciu nepredbehne, rozhodol sa nalákať zákazníkov na to, že bude prijí-mať objednávky aj na šestinové časti pizze. Bude sa teda dať objednať napríklad1/6, 4/6 alebo 15/6 pizze.Navyše Marco vyhlásil, že pizzu nebude pred doručením krájať viac ako

je nutné (aby si ju zákazník mohol nakrájať podľa svojho gusta). Presnejšie,zákazník dostane čo najviac celých pízz a jeden kus tvoriaci necelú časť jehoobjednávky. Teda napríklad zákazník, ktorý si objedná 15/6 pizze, dostane dvecelé pizze a ešte jeden kus veľkosti pol pizze.Presne v okamihu, kedy mu priniesli z tlačiarne rozmnožené reklamné letáky,

si Marco uvedomil, že nebude vôbec ľahké skombinovať objednávky tak, aby munezostala kopa kúskov pizze, ktoré nik nechce. Obrátil sa preto na vás, aby stemu pomohli.Súťažná úloha: Napíšte program, ktorý na vstupe dostane údaje o jed-

notlivých objednávkach a vypočíta, koľko najmenej pízz stačí Marcovi napiecťa vhodne rozkrájať, ak chce uspokojiť všetky objednávky.Formát vstupu: Prvý riadok vstupu obsahuje jedno celé číslo N (1 ≤ N ≤

10 000) – počet objednávok.Nasleduje N riadkov. Každý z nich popisuje jednu objednávku: obsahuje

jedno celé číslo ci (1 ≤ ci ≤ 100) – počet objednaných šestín pizze.Formát výstupu: Na výstup vypíšte jeden riadok a v ňom jedno celé číslo

p – najmenší počet pízz, ktoré stačia na splnenie všetkých objednávok, keď ichMarco upečie a vhodne rozkrája. Nezabudnite na Marcov sľub zákazníkom, žedoručené časti pizze nesmú byť rozkrojené.Príklady:

Page 8: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

6 Zadania domáceho kola kategórie A

Vstup

3223

Výstup

2

Je viac možností, ako uvedené kusy vyrobiť. Napríklad z jednej pizze vyre-žeme dva kusy po 2/6 a druhú rozrežeme napoly a jednu z polovíc doručíme.

Vstup

3453

Výstup

3

V tomto prípade treba kvôli každému z kusov upiecť celú pizzu. Dve pizzesíce majú dostatočnú plochu, ale nevieme ich vhodne nakrájať.

A-I-2 Zasypané mesto

Archeológ Alfréd Hrozný skúma nedávno nájdené zasypané mesto v púšti.Ako prvý krok sa rozhodol, že pomocou sonaru určí, koľko miestností mali spoluvšetky domy v meste.Kus púšte, kde mesto ležalo, si Alfréd pokryl štvorcovou sieťou s rozmermi

M × N . V ruke so sonarom postupne prešiel všetky riadky takto vytvorenejštvorcovej siete a svoje merania si zaznamenal. Pre jednoduchosť predpokladal,že pod každým poľom tejto siete sa nachádza buď kameň, alebo piesok. Nazáklade získaných dát by rád určil, koľko miestností (súvislých oblastí piesku)v zasypanom meste bolo.Súťažná úloha: Na vstupe je daný popis zasypaného mesta, ktoré si pred-

stavujeme ako štvorcovú sieť s rozmermi M × N . Políčka štvorcovej siete súpopísané po riadkoch od horného k spodnému a v jednotlivých riadkoch po-stupne zľava doprava.Alfréd si svoje merania zapísal v skrátenej podobe. Ak bolo v riadku za

sebou x políčok rovnakého typu, zapísal si jednoducho len číslo x. Zo zápisu „32 7ÿ by však ešte nebolo jasné, či je na prvých troch políčkach kamenie alebopiesok. Preto Alfréd zapísal svoje merania nasledovne:

Page 9: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania domáceho kola kategórie A 7

Zápis každého riadku tvorí niekoľko dvojíc nezáporných celých čísel. Prvéčíslo z každej dvojice udáva počet políčok s pieskom, druhé počet nasledujúcichpolíčok s kameňmi.Vašou úlohou je spočítať počet miestností v zasypanom meste. Miestnosť je

súvislá oblasť piesku, ktorú už v žiadnom smere nie je možné zväčšiť. Dve po-líčka štvorcovej siete považujeme za susedné, ak majú spoločnú hranu (spoločnývrchol nestačí).Formát vstupu: V prvom riadku vstupu sa nachádzajú tri nezáporné

číslaM , N a K – počet riadkov a stĺpcov štvorcovej siete mesta a celkový početdvojíc, ktoré popisujú jej obsah. Je známe, že M a N sú menšie než 50 000 a žeK je menšie ako 1 000 000 000.Každý z ďalších K riadkov obsahuje dve nezáporné celé čísla p a q, kde p je

počet políčok zasypaných pieskom a q je počet nasledujúcich políčok, pod kto-rými sú kamene. Políčka sú popísané po riadkoch začínajúc od horného riadkusiete, v rámci jedného riadku vždy zľava doprava. Každá dvojica čísel popisujeúsek, ktorý celý leží v jednom riadku.Pokiaľ sa Vám nepodarí vyriešiť úlohu s vyššie popísanými obmedzeniami

naM , N a K, predpokladajte, žeM a N sú najviac 500 a K je najviac 100 000.Formát výstupu: Na výstup vypíšte jediný riadok a v ňom jediné nezá-

porné číslo – počet miestností v zasypanom meste. Všimnite si, že ak sú úplnevšade kamene, tak je toto číslo rovné nule.Príklad:

Vstup

4 4 70 42 11 00 21 10 13 0

Výstup

3

Page 10: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

8 Zadania domáceho kola kategórie A

Na prvom obrázku je znázornené mesto z príkladu. Na druhom sú uvedenéčísla, ktoré si preň zapísal Alfréd (okrem núl). Na treťom obrázku sú písmenamioznačené miestnosti nachádzajúce sa v meste.

A-I-3 Okružná jazda

V mestečku Blatislava je neuveriteľne komplikovaný dopravný systém. Tvo-ria ho navzájom poprepájané križovatky. V každej križovatke sa môže stretávaťľubovoľne veľa ulíc. Nedávno sa miestny starosta rozhodol, že je čas na reformudopravnej situácie.Najskôr z každej ulice urobil jednosmerku, pričom si dal pozor na to, aby do

každej križovatky aspoň jedna cesta vchádzala a aby z každej križovatky aspoňjedna cesta vychádzala. Následne v každej križovatke zakázal jednu možnosťodbočenia. (Teda ak do križovatky viedlo k ulíc a z nej ℓ ulíc, po zavedenízákazu sa dala prejsť kℓ− 1 spôsobmi.)Reforma mala úspech, Blatislavčanom neuveriteľne sťažila pohyb po uliciach.

Mnohí sa nevedeli dostať do práce, prípadne (tí menej šťastní) z práce domov.Aby starosta podobné tvrdenia vyvrátil, rozhodol sa nájsť okružnú jazdu – cyk-lickú postupnosť ulíc, ktoré nasledujú po sebe, všetky odbočenia v nej sú povo-lené, nikdy nejdeme v protismere a každá ulica v meste sa v tejto postupnostivyskytuje práve raz.Ak by starosta okružnú jazdu našiel, bolo by každému jasné, že z každej

ulice mesta sa dá dostať na každú inú. Všimnite si ale, že takáto postupnosťnemusí existovať. Na to napríklad stačí, aby v meste bola križovatka, z ktorejvychádza menej ulíc ako do nej vchádza.Súťažná úloha: Napíšte program, ktorý zistí, či v meste existuje okružná

jazda, a ak áno, tak jednu ľubovoľnú nájde.Formát vstupu: V prvom riadku vstupu sú dve prirodzené čísla N a M

– počet križovatiek a počet jednosmeriek. Križovatky sú očíslované od 1 do N .Nasleduje M riadkov, každý popisuje jednu ulicu: obsahuje dve čísla u a v

(1 ≤ u, v ≤ N), ktoré hovoria, že z križovatky u vedie jednosmerka do križovatkyv. Medzi každou dvojicou križovatiek vedie v každom smere najviac jedna ulica.Nasleduje N riadkov, i-ty z nich popisuje zakázané odbočenie na križovatke

s číslom i: obsahuje dve čísla u a v (1 ≤ u, v ≤ N), ktoré hovoria, že ak dokrižovatky i prichádzame z križovatky u, nesmieme odísť ulicou vedúcou ku v.Formát výstupu: Ak existuje riešenie, vypíšte jeden riadok a v ňom po-

stupnosť medzerami oddelených čísel v1, v2, . . . , vm (1 ≤ vi ≤ N pre každé i)

Page 11: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania domáceho kola kategórie A 9

takú, že:

• z vi do vi+1 (pre 1 ≤ i ≤ M) vedie ulica,• ak ideme po ulici z vi do vi+1, je povolené odbočiť do ulice z vi+1 do vi+2(pre 1 ≤ i ≤ M),

• každá ulica sa v postupnosti nachádza, t. j. ak existuje ulica z u do v, takexistuje i také, že vi = u a vi+1 = v.

Indexy počítáme cyklicky, t. j. vm+1 = v1 a vm+2 = v2. Ak existuje viacriešení, vypíšte jedno ľubovoľné. Ak neexistuje žiadne riešenie, namiesto po-stupnosti vypíšte reťazec „Okruzna jazda neexistuje.ÿ.Príklady:

Vstup

4 81 22 33 13 41 34 22 44 14 21 42 13 1

Výstup

1 2 3 4 2 4 1 3

1

2

3

4

1

Na obrázku je cestná sieť z prvého príkladu. Šípky okolo križovatiek ukazujúzakázaný smer odbočenia. Vypísaný výstup je jeden z viacerých možných.

Vstup

3 31 22 33 13 21 32 1

Výstup

Okruzna jazda neexistuje.

Page 12: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

10 Zadania domáceho kola kategórie A

A-I-4 Grafomat

V tomto ročníku olympiády sa budeme v teoretickej úlohe stretávať s gra-fomatmi. V študijnom texte uvedenom za zadaním tejto úlohy sú tieto strojepopísané.Súťažná úloha: Napíšte program pre grafomat, ktorý v zadanom 3-grafe

s vyznačenými dvoma vrcholmi nájde najkratšiu cestu medzi nimi a vyznačívrcholy ležiace na tejto ceste. Môžete predpokladať, že cesta vždy existuje.Pokiaľ je najkratších ciest viac, vyberte si ľubovoľnú z nich.V jednom zo zadaných vrcholov bude mať na začiatku premenná x hodnotu

1, v druhom 2 a vo všetkých ostatných vrcholoch bude mať hodnotu 0.Na konci výpočtu by mala mať premenná y hodnotu 1 vo vrcholoch tvoria-

cich jednu najkratšiu cestu a hodnotu 0 v ostatných vrcholoch.Pokúste sa napísať taký program, ktorého časová zložitosť bude závisieť len

na dĺžke zostrojenej cesty a nie na veľkosti celého grafu.

Študijný text

Grafom nazývame ľubovoľnú konečnú množinu V vrcholov grafu spolu smnožinou E hrán, čo sú neusporiadané dvojice vrcholov. Každá hrana tedapredstavuje spojenie medzi dvoma vrcholmi. Žiadne dva vrcholy nie sú spojenéviac ako jednou hranou, žiadna hrana nespája vrchol sám so sebou. Počet hrángrafu budeme označovať N a počet jeho hrán M .

K-graf budeme hovoriť takému grafu, v ktorom z každého vrcholu vediepráve K hrán a konce týchto hrán sú očíslované prirodzenými číslami od 1 poK. Konce jednej hrany môžu byť očíslované rôzne. Pokiaĺ budeme hovoriť ohranách vychádzajúcich z nejakého vrcholu v, budeme spomínať miestne číslahrán (čísla toho konca, ktorým je v) a vzdialené čísla (to sú tie na opačnýchkoncoch hrán). Nasledujúci obrázok ukazuje príklad 2-grafu a 3-grafu.

2

1

2

1

2 1

2

1

2

1

21

3

3 3

3

3 3

2

1

2

1

2 1

2

1

2

1

21

Page 13: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania domáceho kola kategórie A 11

Ohodnotením grafu nazveme priradenie prvkov nejakej konečnej množinyvrcholom grafu - teda napríklad rozdelenie vrcholov na čierne a biele, alebooznačenie vrcholov číslami od 1 po 5.Grafomat je zariadenie na automatické riešenie grafových úloh. Jeho vstu-

pom je ľubovoľný K-graf G spolu s jeho ohodnotením. Výstupom je nejaké ďal-šie ohodnotenie toho istého grafu. Samotný výpočet je vykonávaný automatmiumiestnenými v jednotlivých vrcholoch grafu. Každý automat má svoju pamäťa riadi sa programom. Programy všetkých automatov sú identické. Okrem toho,že automat môže ľubovoľne narábať so svojou pamäťou, môže aj nahliadať dopamäte svojich susedov.Pamäť automatu si môžeme predstaviť ako pascalovské premenné typu inter-

val. Teda každá premenná obsahuje jedno prirodzené číslo, ktoré je z nejakéhopevne zvoleného rozsahu, ktorý nezávisí na veľkosti vstupu. Okrem toho je tiežmožné používať pole takýchto premenných. Opäť, rozmery poľa musia byť do-predu známe a nesmú závisieť od veľkosti vstupu. Žiadne iné typy premenných(neobmedzene veľké čísla, smerníky, . . . ) sa nedajú používať.Zvláštnu rolu hrajú premenné x a y. Premenná x na začiatku výpočtu obsa-

huje vstupné ohodnotenie toho vrcholu grafu, v ktorom program beží, hodnotapremennej y na konci výpočtu určí výstupné ohodnotenie tohto vrcholu. Všetkypremenné s výnimkou premennej x majú svoju počiatočnú hodnotu pevne ur-čenú. Deklarácia premenných vyzerá napríklad takto:

var x: 1..5; { číslo od 1 do 5, na začiatku je to vstup }y: 1..5 = 3; { y je na začiatku 3, na konci výstup }z: array [1..2] of 3..4 = (3, 4); { dvojprvkové pole }

Riadiaci program automatu si môžeme predstavit ako pascalovský program,v ktorom zakážeme používanie rekurzie a dovolíme manipulovať len s premen-nými v pamäti automatu a s premennými v pamäti susedných automatov. Nasvoje vlastné premenné sa automat odkazuje ich menami, ako by to boli oby-čajné pascalovské globálne premenné. Na to, aby sme vedeli odkazovať na pre-menné susedov, využijeme miestne čísla hrán. Presnejšie, nech i je celočíselnývýraz s hodnotou z rozsahu 1 . . .K. Potom S[i].p je výraz predstavujúci pre-mennú p u suseda, do ktorého od nás vedie hrana s miestnym číslom i. (Samoz-rejme, i môže byť ľubovoľný výraz a p ľubovoľné meno premennej.) Premennésusedov sa dajú len čítať.Aby program mohol dávať do súvislosti svoje hrany s hranami svojich suse-

dov, má k dispozící ešte premenne P[1] až P[K], ktoré sú pevne nastavené tak,že P[i] obsahuje vzdialené číslo tej hrany, ktorá má miestne číslo i.

Page 14: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

12 Zadania domáceho kola kategórie A

Použitie si ukážeme na výraze S[i].S[P[i]].x. Označme vrchol, v ktorompráve sme, písmenom v. Výrazy S[i].volaco sú premenné suseda, do ktoréhosa dostaneme hranou s číslom i. Označme tohto suseda písmenom u. Premenná,ktorú chceme, je S[nieco].x. Takže chceme premennú x od niektorého susedavrcholu u. Ale ktorého? Toho, do ktorého sa dostaneme hranou s číslom P[i].To je ale práve vzdialené číslo hrany, ktorou sme do u prišli. Inými slovami, v u jeto jeho miestne číslo hrany, ktorá vedie späť do v. Takže výraz S[i].S[P[i]].xpredstavuje to isté ako výraz x.Ak sa vám to zdá zložité, povieme si to ešte raz v dvoch krokoch. Najskôr

sa vyhodnotí nieco=P[i]. (P[i] je naša lokálna premenná.) Teraz sa pozriemena premennú S[i].S[nieco].x. (To prvé S je naše lokálne pole s premennýmisusedov, to druhé je podobné pole u suseda.) No a tento sused v premennejS[nieco].x vidí to, čo máme v našej premennej x.Výpočet automatu prebieha v taktoch, a to nasledovne: V nultom takte sa

premenné všetkých automatov nastavia na počiatočnú hodnotu a premenné xna vstupné ohodnotenie jednotlivých vrcholov. V každom ďalšom takte sa vždyznova spustí program každého automatu, pričom premenné svojich susedov vidíprogram v stave, v akom boli na začiatku taktu. Aj keď jednotlivé automatybežia súčasne, nemôže sa teda stať, že by jeden čítal z premennej, do ktorejpráve druhý zapisuje.Výpočet pokračuje tak dlho, až kým v nejakom takte všetky automaty ne-

vykonajú špeciálny príkaz stop. Potom sa výpočet zastaví a z premenných ygrafomat prečíta výstupné ohodnotenie grafu. Pokiaľ príkaz stop urobia lenniektoré automaty, výpočet pokračuje a to aj na tých automatoch, ktoré príkazstop spravili. Štruktúra grafu a obsahy premenných P zostávajú po celú dobuvýpočtu nezmenené.Za časovú zložitosť výpočtu budeme považovať počet taktov, ktoré ubehnú

po zastavenie programu. Nijako teda nezávisí na rýchlosti jednotlivých auto-matov. Podobne ako je to u časovej zložitosti klasických algoritmov, nebudemehľadieť na multiplikatívne konštanty a bude nás zaujímať len asymptotické sprá-vanie zložitosti – teda či je lineárna, kvadratická, atď. Prípady, kedy výpočetneskončí, nebudeme pripúšťať, pre úplnosť ale dodajme, že vtedy sa hodnotypremenných musia nutne opakovať.Príklad 1: Je zadaný 3-graf a v ňom vyznačený jeden vrchol v, a to tak,

že jeho premenná x bude inicializovaná jednotkou a ostatné vrcholy budú maťnulu. Napíšte program pre grafomat, ktorý označí všetky vrcholy, do ktorýchsa dá dostať z vrcholu v po hranách, a to tak, že ich premenná y bude mať nakonci výpočtu hodnotu jedna, pre ostatné vrcholy bude mať hodnotu nula.

Page 15: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania domáceho kola kategórie A 13

Riešenie: Inšpirujeme sa prehľadávaním do šírky. V každom takte sa každývrchol pozrie, či je niektorý z jeho susedov už označený. Ak je, tak sa sám označí.Pokiaľ sa označenie nezmení, vrchol volaním stop súhlasí so zastavením. Priebehvýpočtu bude teda vyzerať tak, že po i-tom takte budú označené tie vrcholy,ktorých vzdialenosť od v je menšia alebo rovná i. Výpočet sa zastaví vtedy, keďsa hodnoty premenných prestanú meniť, čo znamená, že po najviac N taktoch.Preto je časová zložitosť nášho programu lineárna od počtu vrcholov (na rozdielod klasického prehľadávania do šírky, ktoré závisí od počtu hrán).Program vyzerá nasledovne:

var x: 0..1; { bol vrchol označený vo vstupe? }y: 0..1 = 0; { je označený teraz? }prev: 0..1 = 0; { predchádzajúci stav }i: 1..3;

beginprev := y; { zapamätáme si, či už bol označený }if x=1 then y := 1; { prenesieme označenie zo vstupu }for i := 1 to 3 do { pozrieme sa na všetkých susedov }if S[i].y <> 0 then { ak je i-ty sused označený }y := 1; { označ aj sám seba }

if y = prev then stop; { ak sa nič nemení, môžeme skončiť }end.

Príklad 2: Majme 2-graf zložený z jedného cyklu párnej dĺžky, teda zvrcholov očíslovaných 0 . . .N − 1, pričom vrchol i je spojený hranou označenou1 s vrcholom (i + 1) mod N a hranou označenou 2 s vrcholom (i − 1) mod N .(Príklad takého grafu pre N = 6 nájdete na obrázku na začiatku tohto textu.)V tomto grafe je vyznačený jeden vrchol v, rovnako ako v predchádzajúcompríklade. Napíšte program pre grafomat, ktorý označí vrchol protiľahlý k v,teda vrchol s číslom (v +N/2) mod N .Riešenie: Vyšleme signál putujúci z vrcholu v v smere jednotkových hrán

rýchlosťou 1 vrchol za takt. Zároveň vyšleme druhý signál putujúci rovnakourýchlosťou opačným smerom. Akonáhle nejaký vrchol zistí, že do neho prišli obasignály, označí sa a signály už ďaľej neposiela.

var x: 0..1; { vstupná značka vrcholu }y: 0..1 = 0; { výstupná značka }l, r: 0..1 = 0; { už týmto vrcholom prešiel signál

Page 16: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

14 Zadania domáceho kola kategórie A

doľava a doprava? }beginif x=1 then { začíname posielať }begin x := 0; l := 1; r := 1; end;

else if (S[2].l=1) and (S[1].r=1) then { signály sa stretli }begin y := 1; stop; end

else if (S[2].l=1) and (l=0) then l := 1 { pošleme doľava }else if (S[1].r=1) and (r=0) then r := 1 { pošleme doprava }else stop; { nič sa nedeje, môzeme končiť }

end.

Page 17: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania domáceho kola kategórie B

B-I-1 Pestovanie mrkvičiek

Janko je majiteľom veľmi úspešnej firmy, zaoberajúcej sa pestovaním mrk-vičiek. Jeho pole, po ktorom sa rád prechádza, je veľká rovina, ktorá sa tiahneod vidím do nevidím celou obrovskou krajinou. Aby Janko presne vedel, kdesú mrkvičky nasadené, rozhodol sa ich nasadiť práve do bodov s celočíselnýmisúradnicami.Teraz sa rozhodol svoje podnikanie rozšíriť a poskytovať mrkvičky aj cez

internet. Objednal si preto pripojenie svojej farmy optickým káblom. Dozvedelsa ale hroznú novinu. Aby sa kábel dostal až ku jeho farme, musí prechádzaťpopod mrkvičkové pole. Na jednom mieste musí vystúpiť na povrch, aby savyhol zavlažovaciemu zariadeniu, a za ním opät zostúpiť pod zem. Spoločnosť,ktorá mu má kábel inštalovať, mu oznámila súradnice, kde na jeho poli kábelvystúpi a kde sa vráti opäť pod zem. Janko teraz počíta, o koľko mrkvičiek kvôlikáblu nad zemou príde. Skúste mu pomôcť.Súťažná úloha: Napíšte program, ktorý pre zadané dva body s celočísel-

nými súradnicami zistí, koľko bodov s celočíselnými súradnicami leží na úsečke,ktorá zadané body spája.Formát vstupu: Prvý riadok vstupu obsahuje súradnice prvého bodu (dve

celé čísla x1, y1 oddelené medzerou). Druhý riadok obsahuje súradnice druhéhobodu x2, y2. Môžete predpokladať, že −109 ≤ x1, x2, y1, y2 ≤ 109 a že sú to dvarôzne body.Formát výstupu: Vypíšte jediný riadok a v ňom jediné číslo – počet bodov

s celočíselnými súradnicami na úsečke spájajúcej body zo vstupu (vrátane jejkoncových bodov).Príklad:

Vstup

1 15 3

Výstup

3

V tomto príklade ide o body [1, 1], [3, 2] a [5, 3].

Page 18: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

16 Zadania domáceho kola kategórie B

B-I-2 Hladný Samo

Hladný Samo sa konečne dočkal. Jeho rodičia práve odišli z domu a on sakonečne môže poriadne najesť. Vkĺzol do bytu, otvoril chladničku a už už sa chcelpustiť do všetkého, čo v nej našiel. Potom sa však pozrel bližšie a pochopil, žekeby sa všetky tieto veci skombinovali v jeho žalúdku, asi by to nemalo najlepšienásledky. Určite by naraz nemal zjesť čokoládu s kečupom, vyprážané kurča smliekom ani kapustu s lekvárom. Narýchlo si preto vytvoril dvojice jedál, ktoréteraz určite nechce naraz zjesť. Samo je však veľmi hladný a preto by toho chcelzjesť čo najviac.Teraz však len smutne pozerá do chladničky a rozmýšla, čo z toho má zjesť.

Pretože ste jeho dobrý kamarát/ka, napíšte mu program, ktorý mu pomôže.Súťažná úloha: Napíšte program, ktorý zistí, koľko najviac toho Samo

môže zjesť bez toho, aby zjedol obe zo zakázanej dvojice.Formát vstupu: Prvý riadok vstupu obsahuje počet potravín v chladničke

N (1 ≤ N ≤ 25). Na nasledujúcich riadkoch sú dvojice čísel i, j (1 ≤ i, j ≤N) reprezentujúce dvojice čísel potravín, ktoré sa nedajú zjesť spolu. Vstup jeukončený dvojicou čísel „0 0ÿ.Formát výstupu: Prvý riadok výstupu má obsahovať čísloM – maximálny

počet potravín, ktoré môže Samo zjesť. V ďalšom riadku má byť M čísel týchtopotravín. Ak existuje viacero možností s rovnakým počtom potravín, vypíšteľubovoľnú jednu z nich.Príklad:

Vstup

51 22 30 0

Výstup

41 3 4 5

B-I-3 Družstvá

Na ihrisku sa zišlo niekoľko detí, ktoré si medzi sebou chcú zahrať bližšienešpecifikovanú loptovú hru. Ich jediný problém je rozdelenie sa do dvoch druž-stiev. Vlastne ich ani veľmi nezaujíma, aby proti sebe hrali družstvá s rovnakýmpočtom hráčov, dôležité je len, aby rovnako silní hráči boli zastúpení v obochdružstvách.

Page 19: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania domáceho kola kategórie B 17

Preto medzi sebou našli dvojice rovnako silných hráčov, ktorí musia hraťproti sebe. Napr. nech na ihrisko prišli Janko, Ferko, Jožko, Peťko a Mirko.Navyše vieme, že Janko určite musí hrať proti Jožkovi a Ferko musí hrať protiPeťkovi. Potom jedno možné rozdelenie do družstiev je:1. družstvo: Janko, Ferko, Mirko2. družstvo: Jožko, PeťkoSúťažná úloha: Na vstupe je počet hráčov a zoznam dvojíc hráčov, ktorí

nemôžu hrať v jednom družstve. Napíšte program, ktorý zistí, či je možné vytvo-riť dve družstvá s požadovanými vlastnosťami. Ak áno, tak jedno také rozdelenievypíše.Formát vstupu: Prvý riadok vstupu obsahuje celé čísla N a M , kde N je

počet hráčov aM je počet dvojíc hráčov, ktorí nemôžu hrať spolu (N ≤ 10 000).Hráči sú očíslovaní číslami od 1 do N . Na každom z nasledujúcich M riadkovsa nachádzajú dve čísla, určujúce dvojicu hráčov, ktorí nemôžu hrať spolu vjednom družstve.Formát výstupu: Prvý riadok výstupu má obsahovať slovo „ANOÿ, ak

aspoň jedno vhodné rozdelenie existuje, a slovo „NIEÿ v opačnom prípade. Vprípade, že nejaké rozdelenie existuje, v druhom riadku výstupu majú byť číslahráčov hrajúcich v jednom z družstiev. Ak existuje viacero správnych rozdelení,vypíšte ľubovoľné jedno z nich.Príklady:

Vstup

5 21 32 4

Výstup

ANO1 2 5

Vstup

5 31 32 32 1

Výstup

NIE

B-I-4 Assembler

Mnoho mladých programátorov túži naučiť sa programovať v assembleri.Prichystali sme pre vás príklad, ktorý vám dáva možnosť si to vyskúšať.

Page 20: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

18 Zadania domáceho kola kategórie B

Budeme uvažovať zjednodušený assembler. K dispozícií je 8 registrov („pre-mennýchÿ) označených R0, . . . , R7. Okrem nich už nie je k dispozícii žiadnaďalšia pamäť. Registre vedia uchovávať ľubovoľne veľké nezáporné celé číslo. Naprácu s nimi máte 6 inštrukcií:

1. inc Ri (increment)

Zvýši hodnotu registra Ri o 1.

2. dec Ri (decrement)

Ak je Ri > 0, zníži hodnotu registra Ri o 1. Ak Ri = 0, tak nespraví nič.Ak je po vykonaní inštrukcie Ri = 0, tak sa nastaví príznak Z na 1. Inaksa Z nastaví na 0.

3. jmp návestie (jump)

Skočí na inštrukciu napísanú za daným návestím (niečo ako goto v Pas-cale/C).

4. test Ri, Rj

Vypočíta bitový súčin (bitwise and) registrov Ri a Rj . Výsledok všakignoruje a len nastaví príznak Z, podľa toho, či je daný súčin 0 alebo nie.Zvyčajne budete túto inštrukciu používať len na overenie, či je register Ri

nulový a to príkazom test Ri, Ri, čo nastaví príznak Z na 1 ak Ri = 0,inak ho nastaví na 0.

5. jz návestie (jump if zero)

V prípade, že je príznak Z nastavený na 1, skočí na dané navestie. Vopačnom prípade pokračuje vo vykonávaní programu.

6. jnz návestie (jump if not zero)

V prípade, že je príznak Z nastavený na 0, skočí na dané návestie.

Pre jednoduchosť budeme do jedného riadku programu písať len jednu in-štrukciu. Pred ľubovoľnou inštrukciou môže byť napísané návestie (oddelené odinštrukcie dvojbodkou). Je to značka v mieste programu, na ktorú sa môžemeodvolávať inštrukciami jmp, jz a jnz.Formálne vyzerá program nasledovne:

Page 21: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania domáceho kola kategórie B 19

〈program〉 ::= 〈riadok〉 | 〈riadok〉 〈program〉〈riadok〉 ::= 〈instrukcia〉 | 〈navestie〉: 〈instrukcia〉

〈instrukcia〉 ::= inc 〈register〉 |dec 〈register〉 |jmp 〈navestie〉 |test 〈register〉,〈register〉 |jz 〈navestie〉 |jnz 〈navestie〉

〈register〉 ::= R0 | R1 | . . . | R7

Pričom 〈navestie〉 je ľubovoľný reťazec neobsahujúci ’:’ (dvojbodku).Inštrukcie programu sa pri jeho spustení vykonávajú zaradom, podľa toho,

ako boli zapísané v programe, začínajúc od prvej inštrukcie. Jedinou výnimkousú inštrukcie jmp, jz a jnz po ktorých môže program pokračovať na inommieste.Príklad: V registroch R1 a R2 sú zapísané nejaké čísla (ostatné registre sú

vynulované). Napíšte program, ktorý do registra R0 zapíše súčet čísel v regis-troch R1 a R2.Riešenie: Najskôr budeme postupne register R1 zmenšovať o 1 a súčasne

zvyšovať hodnotu registra R0, až kým R1 nebude nula. Tým vlastne nasta-víme R0 na hodnotu R1. Potom to isté spravíme aj s registrom R2, čím k R0pripočítame hodnotu R2.

c1: test R1,R1jz c2dec R1inc R0jmp c1

c2: test R2,R2jz koniecdec R2inc R0jmp c2

koniec:

Súťažná úloha:

a) Napíšte program, ktorý zo súboru program.asm načíta program, zo súboruregistre.in načíta počiatočný obsah registrov a odsimuluje výpočet

Page 22: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

20 Zadania domáceho kola kategórie B

programu. V prípade, že výpočet skončí, vypíše do súboru registre.outobsah registrov po ukončení výpočtu.

Príklad:

program.asm

c1: test R1,R1jz koniecdec R1inc R0inc R0jmp c1

koniec:

registre.in

0 47 0 0 0 0 0 0

registre.out

94 0 0 0 0 0 0 0

b) V registroch R1 a R2 sú zapísané nejaké čísla, pričom R2 6= 0 (ostatné re-gistre sú vynulované). Napíšte assemblerovský program, ktorý do registraR0 zapíše zvyšok po delení čísla R1 číslom R2.

Page 23: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania krajského kola kategórie A

A-II-1 Stále ešte zasypané mesto

Archeológ Alfréd Hrozný už s vašou pomocou zmapoval zasypané mesto. Te-raz sa rozhodol, že naženie mladých študentov, nech mu ho spod piesku vyhrabú.Z univerzity sa mu prihlásilo na pomoc N prvákov a N druhákov. Každý z nichštudoval práve jedno z nasledujúcich zameraní: stredovekú históriu, starovekúhistóriu alebo archeológiu.Alfréd by chcel, aby študenti pracovali vo dvojiciach. Nie však hocijakých.

V každej dvojici musí byť druhák, lebo dvaja prváci by boli príliš pochabí.A navyše študenti v každej dvojici by mali mať rôzne zamerania, aby sa ichvedomosti vhodne dopĺňali.Súťažná úloha: Napíšte program, ktorý na vstupe dostane údaje o jed-

notlivých študentoch a zistí, či (a ak áno, ako) sa dajú popárovať tak, aby bolisplnené Alfrédove požiadavky.Snažte sa nájsť program, pri ktorom by nájdenie priradenia bolo čo najefek-

tívnejšie. (Odhliadneme teda od času potrebného na načítanie vstupu a výpisvýstupu.) Dajte si záležať na dôkaze, že váš algoritmus naozaj pre všetky možnévstupy funguje.Formát vstupu: Prvý riadok vstupu obsahuje jedno celé číslo N , ktoré

udáva počet dvojíc študentov, ktoré budeme vyrábať. Nasleduje 2N riadkov,každý popisuje jedného študenta: obsahuje jeho ročník (číslo 1 alebo 2) a jehozameranie (reťazec „stredovekÿ, „starovekÿ alebo „archeologiaÿ). Môžetepredpokladať, že prvákov je rovnako ako druhákov.Formát výstupu: Ak sa študenti nedajú rozdeliť do vhodných dvojíc,

vypíšte o tom správu. V opačnom prípade vypíšte N riadkov, v každom najskôrzameranie prváka a potom zameranie druháka, ktorý s ním bude vo dvojici.Príklad:

Vstup

31 starovek1 starovek2 archeologia1 stredovek2 stredovek2 starovek

Výstup

starovek archeologiastarovek stredovekstredovek starovek

Page 24: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

22 Zadania krajského kola kategórie A

A-II-2 Nová okružná jazda

Z domáceho kola si isto pamätáte mestečko Blatislava a jeho dopravné ťaž-kosti. Napriek tomu si aspoň stručne celú situáciu popíšeme. Blatislavskú do-pravnú sieť tvoria križovatky poprepájané ulicami. Do jednej križovatky môževchádzať ľubovoľný počet ulíc.Na začiatku tohoto ročníka olympiády sa starosta rozhodol spraviť z každej

ulice jednosmerku (tak, aby do každej križovatky vchádzalo rovnako veľa ulícako z nej vychádzalo) a zakázať v každej križovatke jeden spôsob prechodu.Dnes na magistrát dostali prvé výsledky tejto dopravnej reformy: Počet nehôdstúpol o 47 percent.Zasadol krízový štáb, a ten sa rozhodol situáciu riešiť nasledovne: V pr-

vom rade sa zrušia jednosmerky, teda každou ulicou sa bude dať chodiť obomasmermi. Zato sa ale na každej križovatke zakážu až tri spôsoby odbočenia. Tietozákazy budú tiež obojsmerné, t.j. zakáz odbočenia z ulice a na ulicu b zároveňzakazuje odbočiť z ulice b na ulicu a.Majme teda križovatku t > 2 ulíc. Vzhľadom na históriu Blatislavy vieme,

že t je párne, a teda nutne t ≥ 4. Takúto križovatku sa po zavedení zákazovodbočenia bude dať prejsť t(t− 1)− 6 spôsobmi.Opäť ale bude treba presvedčiť občanov, že je nová reforma dobrá.Súťažná úloha: Napíšte program, ktorý dostane na vstupe popis cestnej

siete v Blatislave a nájde v nej okružnú cestu – cyklickú postupnosť na sebanadväzujúcich ulíc takú, že všetky odbočenia v nej sú povolené a obsahuje každúulicu práve raz.Formát vstupu: V prvom riadku vstupu sa nachádzajú dve prirodzené

čísla N a M – počet križovatiek a počet ulíc. Križovatky sú očíslované od 1 doN .Nasledujúcich M riadkov popisuje jednotlivé ulice. V každom z nich sú dve

čísla križovatiek, ktoré daná ulica spája. Môžete predpokladať, že každá ulicaspája dve rôzne križovatky a že medzi každou dvojicou križovatiek vedie najviacjedna ulica.Ďalej nasleduje N riadkov, ktoré popisujú zákazy odbočenia. V i-tom z nich

je 6 čísel: ui,1, vi,1, ui,2, vi,2, ui,3 a vi,3. Tieto čísla hovoria, že v križovatke sčíslom i sú zakázané nasledujúce spôsoby odbočenia: Ak idem z križovatky ui,x

(pre nejaké x ∈ {1, 2, 3}) do križovatky i, nesmiem odbočiť do ulice vedúcejna križovatku vi,x. A pochopiteľne aj naopak, idúc od vi,x nesmiem odbočiťsmerom na ui,x.Formát výstupu: Ak okružná jazda neexistuje, podajte o tom správu. V

Page 25: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania krajského kola kategórie A 23

opačnom poradí vypíšte postupnosť M čísel: čísla križovatiek v poradí, v akomich prechádza jedna možná okružná jazda.

Formálne, vypíšte postupnosť v1, . . . , vM takú, že:

• Pre každé i (1 ≤ i ≤ M) platí, že medzi križovatkami vi a vi+1 naozajvedie ulica.

• Pre každé i (1 ≤ i ≤ M) platí, že ak ideme ulicou z križovatky vi nakrižovatku vi+1, je dovolené odbočiť smerom na križovatku vi+2.

• Každou ulicou ideme práve raz, teda pre každú ulicu existuje i také, že via vi+1 sú vrcholy, ktoré spája.

Indexy počítame cyklicky, teda vm+1 = v1 a vm+2 = v2.Príklad:

Vstup

5 101 22 33 44 55 11 32 43 54 15 25 2 2 3 4 51 3 1 5 3 42 4 2 1 4 53 5 2 3 1 54 1 1 2 3 4

Výstup

1 2 4 5 2 3 5 1 3 4

Page 26: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

24 Zadania krajského kola kategórie A

A-II-3 Rozvoz pizze vo väčšom

Po tom, ako ste Marcovi v domácom kole pomohli, slávi jeho firma úspechy.Marco sa teda rozhodol, že firmu rozšíri a otvorí niekoľko pobočiek na hranicimesta (kde ešte nie je taká silná konkurencia). Potrebuje ale vašu pomoc, abyzistil, kde presne tieto pobočky otvoriť.Pre jednoduchosť si predstavme, že hranica mesta je kružnica, ktorú si roz-

delíme na N úsekov (mestské časti). Je nutné, aby každý úsek bol celý obsluho-vaný jednou pizzériou, aby obyvatelia nemali zmätok a jasne vedeli, do ktorejpizzérie majú ísť. Navyše každá pizzéria musí pochopiteľne obsluhovať súvislýkus hranice mesta, teda niekoľko po sebe nasledujúcich úsekov.Posledný problém je veľmi jednoduchý: jedna pizzéria dokáže denne obslúžiť

najviac K zákazníkov. Pre každý úsek hranice mesta vie Marco povedať, koľkozákazníkov tam denne bude mať. Pizzérie teda treba rozmiestniť tak, aby žiadnaz nich nemala v obsluhovaných úsekoch dokopy viac ako K zákazníkov denne.Súťažná úloha: Napíšte program, ktorý načíta kapacitu jednej pizzérie,

počet úsekov a údaje o počtoch zákazníkov v nich, a spočíta, koľko najmenejpizzérií musí Marco postaviť, aby obslúžil zákazníkov zo všetkých úsekov, a akoim prideliť úseky.Formát vstupu: V prvom riadku vstupu sú dve prirodzené čísla N a K –

počet úsekov kružnice a počet zákazníkov, ktorých denne zvládne obslúžiť jednapizzéria.Nasleduje N riadkov, každý popisuje jeden úsek kružnice v poradí, v akom

na nej ležia. Pritom i-ty z týchto riadkov obsahuje jedno celé číslo Ai – početzákazníkov, ktorých treba v tomto úseku denne obslúžiť.Môžete predpokladať, že žiadne Ai nie je väčšie ako K.Formát výstupu: V prvom riadku vypíšte minimálny počet pizzérií M .V nasledujúcich M riadkoch vypíšte popis jedného optimálneho riešenia.

Presnejšie, v i-tom riadku vypíšte číslo Si prvého a číslo Ti posledného úseku,ktorý bude obsluhovať i-ta pizzéria.(Ak Ti < Si, znamená to, že táto pizzéria obsluhuje úseky Si, . . . , N, 1, . . . , Ti,

inak pizzéria obsluhuje úseky Si, . . . , Ti.)Pripomíname, že v optimálnom riešení musí byť každý úsek obsluhovaný

práve jednou pizzériou, a navyše pre každú pizzériu musí byť súčet počtov zá-kazníkov v jej úsekoch nanajvýš rovný K.Príklad:

Page 27: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania krajského kola kategórie A 25

Vstup

7 114476642

Výstup

46 12 34 45 5

Prvá pizzéria obsluhuje úseky 6, 7 a 1, v tých je dokopy 4 + 2 + 4 = 10zákazníkov. Druhá bude mať 4 + 7 = 11 zákazníkov, tretia a štvrtá po 6.

A-II-4 Grafomat loví zver

Študijný text je identický s tým zo zadaní domáceho kola (úloha A-I-4).Súťažná úloha: Kráľ Miesiželezo XXXXVII. veľmi rád organizoval lovy.

Priečilo sa mu na nich ale strieľanie do všetkého živého, či už to boli zvieratá,alebo zablúdení poľovníci. Preto si dal vyrobiť mechanickú zver a mechanickýchlovcov, a mohlo sa ísť loviť.Mechanickí lovci vždy zahnali zviera do nory a utvorili okolo nej kruhovú

formáciu. Každý lovec sa pripojil ku svojim susedom a všetci svorne čakali. Lenčo si niekto všimol, že zviera vystrčilo z nory anténky, poslal správu ostatnýma všetci naraz vystrelili. (Smerom do nory, nie na seba!)Vašou úlohou je napísať program, ktorý bude lovcov riadiť.Majme 2-graf, tvorený jedným cyklom párnej dĺžky. Vrcholy sú očíslované od

0 doN−1, pričom vrchol i je spojený (hranou číslo 1) s vrcholom ((i+1) mod N)a (hranou číslo 2) s vrcholom ((i − 1) mod N). Príklad takéhoto 2-grafu je naprvom obrázku v študijnom texte.Váš program sa má správať nasledovne: Ak je pri spustení vo všetkých vr-

choloch x = 0, skončí s y = 0 v každom vrchole. Ak dostane v jednom vrcholex = 1 a v ostatných x = 0, v konečnom čase skončí s tým, že vo všetkých vr-choloch bude y = 1, pričom po každom z predchádzajúcich krokov muselovšade byť y = 0.Slovne: Ak lovci nič nevidia, nestrieľajú. Ak práve jeden zazrie zver, po ko-

nečnom čase všetci naraz vystrelia. Môžete predpokladať, že pri spustení bude

Page 28: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

26 Zadania krajského kola kategórie A

nanajvýš v jednom vrchole x = 1. Ak sa vám to hodí, môžete navyše predpo-kladať, že N je vhodného tvaru (napr. štvorec, mocnina dvoch, a pod.).

Page 29: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania krajského kola kategórie B

B-II-1 Kerfúr ten je lacnejší

Podobné tvrdenia počúvame denne od marketingových oddelení supermar-ketov. Je však možné, aby všetci hovorili pravdu? To by veľmi zaujímalo úradpre ochranu spotrebiteľa. Ten pozorne sledoval reklamy a zapisoval si z nichtvrdenia typu „Supermarket A je lacnejší ako supermarket Bÿ. Teraz by chcelizistiť, či to môže byť naozaj všetko pravda.Súťažná úloha: Napíšte program, ktorý dostane na vstupe reklamy a zistí,

či takáto situácia môže nastať. Pre jednoduchosť predpokladajme, že všetkysupermarkety predávajú rovnaké výrobky a ak reklama hovorí, že supermarketA je lacnejši ako B, znamená to, že všetky výrobky majú v A ostro menšiu cenuako v B. Zároveň predpokladáme, že počas doby, kedy úrad sledoval reklamy,sa ceny v žiadnom supermarkete nemenili.Formát vstupu: Prvý riadok vstupu obsahuje celé čísla N a M , kde N

je počet skúmaných supermarketov a M je počet reklám. Na nasledujúcich Mriadkoch sa nachádzajú dvojice celých čísel i, j (1 ≤ i, j ≤ N) s významom„supermarket číslo i je lacnejší ako supermarket číslo jÿ.Formát výstupu: Jediný riadok výstupu má obsahovať slovo ANO ak môžu

byť pravdivé úplne všetky reklamy zo vstupu, prípadne NIE, ak to nie je možné.Príklady:

Vstup

3 31 22 33 1

Výstup

NIE

Vstup

7 41 44 74 66 7

Výstup

ANO

Page 30: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

28 Zadania krajského kola kategórie B

B-II-2 Televízna súťaž

V istej televíznej súťaži je finalista postavený pred mnoho dverí, pričom lenza jednými z nich je skrytá hlavná cena, za ostatnými nie je nič. To, za ktorými znich je hlavná cena, rozhoduje náhoda. Pred začiatkom súťaže sa vyrobí niekoľkolístočkov a na každý z nich sa napíše jedno číslo dverí. (To isté číslo môže byťnapísané na viacerých lístočkoch, a niektoré čísla dokonca nemusia byť použitévôbec.) Potom tesne pred finále vyžrebuje moderátor jeden z lístočkov a zadvere, ktorých číslo je na lístočku, sa uloží hlavná cena.Hráč má možnosť vidieť lístočky dopredu, aby vedel, že usporiadateľ ne-

podvádza. Aké číslo dverí si má vybrať, aby pravdepodobnosť, že vyhrá, bolanajväčšia?Súťažná úloha: Napíšte program, ktorý zistí ktoré zo zadaných čísel sa vo

vstupe vyskytuje najčastejšie.Formát vstupu: Prvý riadok vstupu obsahuje počet lístkov N (1 ≤ N ≤

10 000). V nasledujúcom riadku je N celých čisel oddelených medzerami. Tietočísla sú v rozmedzí od 1 do 109.Formát výstupu: Prvý riadok výstupu má obsahovať jediné číslo k, ktoré

sa medzi vstupnými číslami vyskytovalo najčastejšie.Ak je viacero možných odpovedí, môžete vypísať ľubovoľnú jednu z nich.Príklad:

Vstup

5100 23 4321 100 47

Výstup

100

B-II-3 Kartári

Miško a Lacko sú veľkí kartári. Skoro nikdy ich neuvidíte robiť niečo inéako hrať karty. Najradšej hrajú hru Rah, ktorú si sami vymysleli. Nebudeme tuvysvetľovať jej presné pravidlá, sú totiž dosť komplikované.Dôležité je, že táto hra sa hrá s klasickými žolíkovými kartami (bez žolíkov).

V balíku je teda 8 kusov každej možnej hodnoty. Farby kariet pre nás nebudúdôležité.Hodnoty kariet označíme znakmi nasledovne: dvojke až deviatke budú zod-

povedať znaky ‘2’ až ‘9’. Desiatka bude ‘T’ (z anglického ten), a ďalej to užpôjde podľa písmen na kartách, teda jano bude ‘J’, dáma ‘Q’, kráľ ‘K’ a eso ‘A’.

Page 31: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania krajského kola kategórie B 29

Obidvaja hráči majú svoju kôpku kariet (na začiatku hry prázdnu). Potomsa striedajú v ťahoch. V jednom ťahu si hráč buď môže zobrať nejakú kartu zbalíka a dať si ju na spodok svojej kôpky, alebo zahrať kartou, ktorú má navrchu kôpky.Miško však začal Lacka podozrievať, že podvádza. Preto by potreboval prog-

ram, ktorý by mu presne vedel povedať, akou kartou má kedy Lacko zahrať, akvie, aké karty si Lacko vyberal z balíka.Súťažná úloha: Napíšte program, ktorý bude načítavať kroky, ktoré Lacko

vykonáva. V prípade, že Lacko chce zahrať kartou z vrchu svojej kôpky, vypíštekartu, ktorou zahral. (Pozor, partia môže byť ľubovoľne dlhá, Lacko môže opäťzobrať do kôpky karty, ktoré už predtým zahral.)Formát vstupu: Každý riadok vstupu obsahuje jeden príkaz. Príkazy môžu

byť nasledovných typov:

• 1 c – Lacko zobral z balíka kartu c (c je jeden zo znakov 23456789TJQKA)• 2 – Lacko sa rozhodol zahrať kartou z vrchu svojej kôpky• 0 – koniec vstupuFormát výstupu: Pre každý riadok vstupu s príkazom 2 má výstup obsa-

hovať jeden riadok a v ňom jeden znak, označujúci kartu, ktorou Lacko zahral.Môžete predpokladať, že vždy, keď má zahrať kartu, nejakú v kôpke má.Príklad:

Vstup

1 J1 A21 31 J220

Výstup

JA3

B-II-4 Assembler II

a) (3 body) Definujte pomocou existujúcich inštrukcií nové inštrukcie:– „mov Ri, Rjÿ, ktorá priradí do registra Ri hodnotu registra Rj

– „mul Ri, Rjÿ, ktorá priradí do registra Ri súčin hodnôt Ri a Rj .

Page 32: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

30 Zadania krajského kola kategórie B

b) (7 bodov) V registri R1 je uložené nezáporné celé číslo, ostatné registresú vynulované. Napíšte program v našom assembleri, ktorý do registra R0zapíše dolnú celú časť odmocniny z R1 (teda najväčšie celé k také, že k2

je menšie alebo rovné ako hodnota v R1).Snažte sa, aby váš program bol efektívny, t.j. potreboval čo najmenejinštrukcií v závislosti od veľkosti čísla v R1.

Inštrukcie mov a mul majú nechať obsah registra Rj nezmenený. Môžetepredpokladať, že i 6= j, že i, j < 5 a že registre R5, R6 a R7 sú pred vykonanímvašej inštrukcie vynulované. Musia byť nulové aj po vykonaní vašej inštrukcie,ale počas vykonávania ich môžete použiť ako pomocné premenné.Pri riešení súťažných úloh si môžete na skrátenie zápisu programu podobne

definovať aj iné nové inštrukcie.

Študijný text

Budeme uvažovať zjednodušený assembler. K dispozícií je 8 registrov („pre-mennýchÿ) označených R0, . . . , R7. Okrem nich už nie je k dispozícii žiadnaďalšia pamäť. Registre vedia uchovávať ľubovoľne veľké nezáporné celé číslo. Naprácu s nimi máte 6 inštrukcií:

1. inc Ri (increment)

Zvýši hodnotu registra Ri o 1.2. dec Ri (decrement)

Ak je Ri > 0, zníži hodnotu registra Ri o 1. Ak Ri = 0, tak nespraví nič.Ak je po vykonaní inštrukcie Ri = 0, tak sa nastaví príznak Z na 1. Inaksa Z nastaví na 0.

3. jmp návestie (jump)

Skočí na inštrukciu napísanú za daným návestím (ako goto v Pascale/C).4. test Ri, Rj

Vypočíta bitový súčin (bitwise and) registrov Ri a Rj . Výsledok všakignoruje a len nastaví príznak Z, podľa toho, či je daný súčin 0 alebo nie.Zvyčajne budete túto inštrukciu používať len na overenie, či je register Ri

nulový a to príkazom test Ri, Ri, čo nastaví príznak Z na 1 ak Ri = 0,inak ho nastaví na 0.

Page 33: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania krajského kola kategórie B 31

5. jz návestie (jump if zero)

V prípade, že je príznak Z nastavený na 1, skočí na dané navestie. Vopačnom prípade pokračuje vo vykonávaní programu.

6. jnz návestie (jump if not zero)

V prípade, že je príznak Z nastavený na 0, skočí na dané návestie.

Pre jednoduchosť budeme do jedného riadku programu písať len jednu in-štrukciu. Pred ľubovoľnou inštrukciou môže byť napísané návestie (oddelené odinštrukcie dvojbodkou). Je to značka v mieste programu, na ktorú sa môžemeodvolávať inštrukciami jmp, jz a jnz.Formálne vyzerá program nasledovne:

〈program〉 ::= 〈riadok〉 | 〈riadok〉 〈program〉〈riadok〉 ::= 〈instrukcia〉 | 〈navestie〉: 〈instrukcia〉

〈instrukcia〉 ::= inc 〈register〉 | dec 〈register〉 |jmp 〈navestie〉 | test 〈register〉,〈register〉 |jz 〈navestie〉 | jnz 〈navestie〉

〈register〉 ::= R0 | R1 | . . . | R7

Pričom 〈navestie〉 je ľubovoľný reťazec neobsahujúci ’:’ (dvojbodku).Inštrukcie programu sa pri jeho spustení vykonávajú zaradom, podľa toho,

ako boli zapísané v programe, začínajúc od prvej inštrukcie. Výnimkou sú in-štrukcie jmp, jz a jnz po ktorých môže program pokračovať na inom mieste.

Príklad: V registroch R1 a R2 sú zapísané ne-jaké čísla (ostatné registre sú vynulované). Napíšteprogram, ktorý do registra R0 zapíše súčet čísel vregistroch R1 a R2.

Riešenie: Najskôr budeme postupne register R1zmenšovať o 1 a súčasne zvyšovať hodnotu registraR0, až kým R1 nebude nula. Tým vlastne nasta-víme R0 na hodnotu R1. Potom to isté spravíme ajs registrom R2, čím k R0 pripočítame hodnotu R2.

c1: test R1,R1jz c2

dec R1

inc R0jmp c1

c2: test R2,R2jz koniec

dec R2

inc R0jmp c2

koniec:

Page 34: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania celoštátneho kola kategórie A

A-III-1 Pizza vracia úder

Marec, mesiac daňových priznaní, zbrzdil rozmach Marcovej firmy. Počasrozvážania pizze a zakladania nových pobočiek nemal Marco čas zaoberať saúčtovníctvom, a teraz s hrôzou zistil, že si do svojich poznámok zabudol zapí-sať, čo sú príjmy a čo výdaje. Napriek tomu nespanikáril, lebo si spomenul napríbehy, ktoré mu rozprával jeho dedo (bývalá hlava talianskej mafie) a rozhodolsa doplniť (čítaj: sfalšovať) účtovné záznamy.Aby výsledok vyzeral čo najdôveryhodnejšie, rozhodol sa použiť čísla zo svo-

jich poznámok a vybrať si pri každom čísle, či je to výdaj alebo príjem. Naviacsa rozhodol, že keď už falšovať, tak poriadne. Rád by vyzeral ako úspešný ob-chodník, a teda neskončil v strate. Na druhej strane by chcel platiť čo najmenšiedane, teda jeho zisk by mal byť čo najmenší. Pri riešení tejto neľahkej úlohy bymu mohlo pomôcť to, že veľkosť čísel v jeho poznámkach je podstatne menšiaako ich počet.Súťažná úloha: Je daných N prirodzených čísel a1, . . . , aN z rozsahu 1

až K. Hodnota K je väčšinou rádovo menšia ako N . Vašou úlohou je nájsť číslasi ∈ {−1,+1} také, že súčet z = s1a1+s2a2+. . .+sNaN je nezáporný a zároveňnajmenší možný.Formát vstupu: záznamov.Druhý riadok obsahuje N hodnôt a1, . . . , aN – jednotlivé účtovné záznamy.Formát výstupu: i-tu položku ako príjem a - ak ju má brať ako výdaj.Príklady:

Vstup

41 2 3 4

Výstup

+--+

Platí + a1 − a2 − a3 + a4 = 0 a lepšieto zjavne nejde.

Page 35: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania celoštátneho kola kategórie A 33

Vstup

10002 3 3 3 3 3 ... 3 3 3 3 3 3

Výstup

---...+++

Veľkú časť vstupu aj výstupu sme preprehľadnosť vynechali.Vo výstupe je najskôr 500 znakov -,potom 500 znakov +. Výsledný zisk je1. Zisk 0 sa zjavne dosiahnuť nedá,preto je toto riešenie optimálne.

A-III-2 Obdĺžnik

Súťažná úloha: V rovine je danýchN navzájom rôznych bodovB1, . . . , BN .Vašou úlohou je navrhnúť algoritmus, ktorý nájde obdĺžnik A1A2A3A4,

ktorého vrcholy sú niektoré zo zadaných bodov (t. j. A1 = Bi pre nejaké i,1 ≤ i ≤ N , analogicky pre A2, A3 a A4). Hrany obdĺžnika A1A2A3A4 musia byťrovnobežné s osami, teda x-ové súradnice vrcholov A1 a A4 a vrcholov A2 a A3musia byť rovnaké a rovnako y-ové súradnice vrcholov A1 a A2 a vrcholov A3 aA4 musia byť rovnaké.Navyše počet bodov Bi, ktoré ležia vo vnútri alebo na obvode vami nájde-

ného obdĺžnika A1A2A3A4, musí byť maximálny možný.Formát vstupu: Nasleduje N riadkov, pričom i-ty riadok obsahuje súrad-

nice i-teho bodu.Formát výstupu: podmienky zo zadania. Ak sa zo zadaných bodov nedá

vytvoriť žiadny vhodný obdĺžnik, vypíšte namiesto toho správu „Neexistujevhodný obdĺžnikÿ.Príklady:

Page 36: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

34 Zadania celoštátneho kola kategórie A

Vstup

71 12 14 11 34 32 53 5

Výstup

5

Takto vyzerá situácia popisovanátýmto vstupom a jediné optimálne rie-šenie:

[1, 1] [2, 1] [4, 1]

[1, 3] [4, 3]

[2, 5] [3, 5]

x

y

Vstup

41 12 11 24 7

Výstup

Neexistuje vhodný obdĺžnik

A-III-3 Grafomat a šamani

V osadách indiánskeho kmeňa Apačov-Grafomatérov sa zajtra koná najväč-šia slávnosť roka, pri ktorej majú šamani kmeňu zabezpečiť náklonnosť veľkéhoManitú pri tohtoročnom love bizónov.

Page 37: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania celoštátneho kola kategórie A 35

Rituál vyžaduje, aby sa indiáni v niektorých osadách pomaľovali na červenoa v ostatných osadách na modro. No a šamani vedia, že rituál bude úspešný lenvtedy, ak bude „červenýchÿ a „modrýchÿ osád rovnako. A tak teraz v každejosade šaman stojí pri svojom signálnom ohni a snaží sa so susednými osadamidohodnúť, akou farbou sa vlastne kde majú maľovať.Súťažná úloha: Napíšte program pre grafomat, ktorý v zadanom 3-grafe

s jedným označeným vrcholom označí presne polovicu vrcholov grafu a skončí.Presnejšie, váš program sa má správať nasledovne: Na začiatku je v jednom

vrchole grafu x = 1 a vo všetkých ostatných x = 0. Na konci výpočtu má byť vpráve polovici vrcholov y = 1 (tieto vrcholy predstavujú „červenéÿ dediny) a vostatných vrcholoch má byť y = 0.Môžete predpokladať, že graf je súvislý a že má párny počet vrcholov, takže

hľadané rozdelenie vždy existuje. (Dá sa dokázať, že dokonca každý 3-graf mápárny počet vrcholov, ale pre riešenie úlohy to nie je podstatné.)Rady a upozornenia: Ak si s úlohou neviete poradiť, rozmyslite si najskôr,

ako by ste ju riešili, ak by použitým grafom nebol 3-graf ale strom (súvislý grafbez cyklov).Dajte si pozor na to, že počet stavov každého automatu musí byť konečný,

teda nemôžete používať premenné, ktorých veľkosť by závisela od veľkostigrafu.

Študijný text

Študijný text je identický s tým z domáceho kola až na definíciu ukončeniavýpočtu a príslušnú úpravu riešenia príkladov.

Grafom nazývame ľubovoľnú konečnú množinu V vrcholov grafu spolu smnožinou E hrán, čo sú neusporiadané dvojice vrcholov. Každá hrana tedapredstavuje spojenie medzi dvoma vrcholmi. Žiadne dva vrcholy nie sú spojenéviac ako jednou hranou, žiadna hrana nespája vrchol sám so sebou. Počet hrángrafu budeme označovať N a počet jeho hrán M .

K-graf budeme hovoriť takému grafu, v ktorom z každého vrcholu vediepráve K hrán a konce týchto hrán sú očíslované prirodzenými číslami od 1 poK. Konce jednej hrany môžu byť očíslované rôzne. Pokiaĺ budeme hovoriť ohranách vychádzajúcich z nejakého vrcholu v, budeme spomínať miestne číslahrán (čísla toho konca, ktorým je v) a vzdialené čísla (to sú tie na opačnýchkoncoch hrán). Nasledujúci obrázok ukazuje príklad 2-grafu a 3-grafu.

Page 38: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

36 Zadania celoštátneho kola kategórie A

2

1

2

1

2 1

2

1

2

1

21

3

3 3

3

3 3

2

1

2

1

2 1

2

1

2

1

21

Ohodnotením grafu nazveme priradenie prvkov nejakej konečnej množinyvrcholom grafu - teda napríklad rozdelenie vrcholov na čierne a biele, alebooznačenie vrcholov číslami od 1 po 5.Grafomat je zariadenie na automatické riešenie grafových úloh. Jeho vstu-

pom je ľubovoľný K-graf G spolu s jeho ohodnotením. Výstupom je nejaké ďal-šie ohodnotenie toho istého grafu. Samotný výpočet je vykonávaný automatmiumiestnenými v jednotlivých vrcholoch grafu. Každý automat má svoju pamäťa riadi sa programom. Programy všetkých automatov sú identické. Okrem toho,že automat môže ľubovoľne narábať so svojou pamäťou, môže aj nahliadať dopamäte svojich susedov.Pamäť automatu si môžeme predstaviť ako pascalovské premenné typu inter-

val. Teda každá premenná obsahuje jedno prirodzené číslo, ktoré je z nejakéhopevne zvoleného rozsahu, ktorý nezávisí na veľkosti vstupu. Okrem toho je tiežmožné používať pole takýchto premenných. Opäť, rozmery poľa musia byť do-predu známe a nesmú závisieť od veľkosti vstupu. Žiadne iné typy premenných(neobmedzene veľké čísla, smerníky, . . . ) sa nedajú používať.Zvláštnu rolu hrajú premenné x a y. Premenná x na začiatku výpočtu obsa-

huje vstupné ohodnotenie toho vrcholu grafu, v ktorom program beží, hodnotapremennej y na konci výpočtu určí výstupné ohodnotenie tohto vrcholu. Všetkypremenné s výnimkou premennej x majú svoju počiatočnú hodnotu pevne ur-čenú. Deklarácia premenných vyzerá napríklad takto:

var x: 1..5; { číslo od 1 do 5, na začiatku je to vstup }y: 1..5 = 3; { y je na začiatku 3, na konci výstup }z: array [1..2] of 3..4 = (3, 4); { dvojprvkové pole }

Riadiaci program automatu si môžeme predstavit ako pascalovský program,v ktorom zakážeme používanie rekurzie a dovolíme manipulovať len s premen-nými v pamäti automatu a s premennými v pamäti susedných automatov. Na

Page 39: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania celoštátneho kola kategórie A 37

svoje vlastné premenné sa automat odkazuje ich menami, ako by to boli oby-čajné pascalovské globálne premenné. Na to, aby sme vedeli odkazovať na pre-menné susedov, využijeme miestne čísla hrán. Presnejšie, nech i je celočíselnývýraz s hodnotou z rozsahu 1 . . .K. Potom S[i].p je výraz predstavujúci pre-mennú p u suseda, do ktorého od nás vedie hrana s miestnym číslom i. (Samoz-rejme, i môže byť ľubovoľný výraz a p ľubovoľné meno premennej.) Premennésusedov sa dajú len čítať.Aby program mohol dávať do súvislosti svoje hrany s hranami svojich suse-

dov, má k dispozící ešte premenne P[1] až P[K], ktoré sú pevne nastavené tak,že P[i] obsahuje vzdialené číslo tej hrany, ktorá má miestne číslo i.Použitie si ukážeme na výraze S[i].S[P[i]].x. Označme vrchol, v ktorom

práve sme, písmenom v. Výrazy S[i].volaco sú premenné suseda, do ktoréhosa dostaneme hranou s číslom i. Označme tohto suseda písmenom u. Premenná,ktorú chceme, je S[nieco].x. Takže chceme premennú x od niektorého susedavrcholu u. Ale ktorého? Toho, do ktorého sa dostaneme hranou s číslom P[i].To je ale práve vzdialené číslo hrany, ktorou sme do u prišli. Inými slovami, v u jeto jeho miestne číslo hrany, ktorá vedie späť do v. Takže výraz S[i].S[P[i]].xpredstavuje to isté ako výraz x.Ak sa vám to zdá zložité, povieme si to ešte raz v dvoch krokoch. Najskôr

sa vyhodnotí nieco=P[i]. (P[i] je naša lokálna premenná.) Teraz sa pozriemena premennú S[i].S[nieco].x. (To prvé S je naše lokálne pole s premennýmisusedov, to druhé je podobné pole u suseda.) No a tento sused v premennejS[nieco].x vidí to, čo máme v našej premennej x.Výpočet automatu prebieha v taktoch, a to nasledovne: V nultom takte sa

premenné všetkých automatov nastavia na počiatočnú hodnotu a premenné xna vstupné ohodnotenie jednotlivých vrcholov. V každom ďalšom takte sa vždyznova spustí program každého automatu, pričom premenné svojich susedov vidíprogram v stave, v akom boli na začiatku taktu. Aj keď jednotlivé automatybežia súčasne, nemôže sa teda stať, že by jeden čítal z premennej, do ktorejpráve druhý zapisuje.

Zmena oproti krajskému kolu:Výpočet pokračuje tak dlho, až kým po nejakom takte neplatí, že všetky pre-menné vo všetkých automatoch majú rovnakú hodnotu ako mali po predchá-dzajúcom takte. Inými slovami, výpočet končí, akonáhle sa v nejakom takte užnič nové nestane. Vtedy grafomat prečíta z premenných y výstupné ohodnoteniegrafu.

Štruktúra grafu a obsahy premenných P zostávajú po celú dobu výpočtu

Page 40: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

38 Zadania celoštátneho kola kategórie A

nezmenené.Za časovú zložitosť výpočtu budeme považovať počet taktov, ktoré ubehnú

po zastavenie programu. Nijako teda nezávisí na rýchlosti jednotlivých auto-matov. Podobne ako je to u časovej zložitosti klasických algoritmov, nebudemehľadieť na multiplikatívne konštanty a bude nás zaujímať len asymptotické sprá-vanie zložitosti – teda či je lineárna, kvadratická, atď. Prípady, kedy výpočetneskončí, nebudeme pripúšťať, pre úplnosť ale dodajme, že vtedy sa hodnotypremenných musia nutne opakovať.Príklad 1: Je zadaný 3-graf a v ňom vyznačený jeden vrchol v, a to tak,

že jeho premenná x bude inicializovaná jednotkou a ostatné vrcholy budú maťnulu. Napíšte program pre grafomat, ktorý označí všetky vrcholy, do ktorýchsa dá dostať z vrcholu v po hranách, a to tak, že ich premenná y bude mať nakonci výpočtu hodnotu jedna, pre ostatné vrcholy bude mať hodnotu nula.Riešenie: Inšpirujeme sa prehľadávaním do šírky. V každom takte sa každý

vrchol pozrie, či je niektorý z jeho susedov už označený. Ak je, tak sa sám označí.Pokiaľ sa označenie vrcholu nezmení, vrchol tým vlastne hovorí, že súhlasí sozastavením. Priebeh výpočtu bude teda vyzerať tak, že po i-tom takte budúoznačené tie vrcholy, ktorých vzdialenosť od v je menšia alebo rovná i. Výpočetsa zastaví vtedy, keď sa hodnoty premenných prestanú meniť, čo znamená, žepo najviac N taktoch. Preto je časová zložitosť nášho programu lineárna odpočtu vrcholov (na rozdiel od klasického prehľadávania do šírky, ktoré závisí odpočtu hrán).Program vyzerá nasledovne:

var x: 0..1; { bol vrchol označený vo vstupe? }y: 0..1 = 0; { je označený teraz? }i: 1..3;

beginif x=1 then y := 1; { prenesieme označenie zo vstupu }for i := 1 to 3 do { pozrieme sa na všetkých susedov }if S[i].y <> 0 then { ak je i-ty sused označený }y := 1; { označ aj sám seba }

end.

Príklad 2: Majme 2-graf zložený z jedného cyklu párnej dĺžky, teda zvrcholov očíslovaných 0 . . .N − 1, pričom vrchol i je spojený hranou označenou1 s vrcholom (i + 1) mod N a hranou označenou 2 s vrcholom (i − 1) mod N .(Príklad takého grafu pre N = 6 nájdete na obrázku na začiatku tohto textu.)V tomto grafe je vyznačený jeden vrchol v, rovnako ako v predchádzajúcom

Page 41: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania celoštátneho kola kategórie A 39

príklade. Napíšte program pre grafomat, ktorý označí vrchol protiľahlý k v,teda vrchol s číslom (v +N/2) mod N .Riešenie: Vyšleme signál putujúci z vrcholu v v smere jednotkových hrán

rýchlosťou 1 vrchol za takt. Zároveň vyšleme druhý signál putujúci rovnakourýchlosťou opačným smerom. Akonáhle nejaký vrchol zistí, že do neho prišli obasignály, označí sa a signály už ďalej neposiela.

var x: 0..1; { vstupná značka vrcholu }y: 0..1 = 0; { výstupná značka }l, r: 0..1 = 0; { už týmto vrcholom prešiel signál

begin doľava a doprava? }if x=1 then beginx := 0; l := 1; r := 1; { začíname posielať }

end else if (S[2].l=1) and (S[1].r=1) theny := 1 { signály sa stretli }

else if (S[2].l=1) and (l=0) thenl := 1 { prišiel signál zľava }

else if (S[1].r=1) and (r=0) thenr := 1; { prišiel signál sprava }

end. { inak sa v tomto vrchole teraz nič nedeje }

Zjavne výpočet tohto grafomatu skončí presne po (N/2) + 2 taktoch. Po(N/2) + 1 taktoch budeme v situácii, kedy:

• začiatočný vrchol bude mať x = 0, l = r = 1,• N − 1 vrcholov naľavo od neho bude mať l = 1,• N − 1 vrcholov napravo bude mať r = 1,• no a vrchol oproti bude mať l = r = 0 a y = 1.

V nasledujúcom takte sa už žiadna premenná v žiadnom vrchole nezmení, ateda výpočet končí.

A-III-4 Polícia zasahuje

V meste Blatislava sa tentokrát usídlila mafia. Keď už jej výčiny prekročiliúnosnú medzu, bola miestna polícia poverená zatrhnúť jej ich.Keď však mafiáni zistili, že ich sleduje polícia, vymysleli si fintu. Začali medzi

svojimi domami chodiť cez mestskú kanalizáciu. Polícia to práve včera odhalilaa rozhodla sa, že postaví do kanalizácie pod niektoré domy hliadky tak, aby sauž žiadni dvaja mafiáni k sebe nedostali.

Page 42: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

40 Zadania celoštátneho kola kategórie A

Vmeste jeN domov. Niektoré z nich patria mafii, niektoré bežným občanom.Z každého domu sa dá dostať do kanalizácie. Kanalizačný systém vyzerá tak, žemedzi každými dvoma domami sa ním dá prejsť práve jedným spôsobom (ak,pravda, nechceme ísť žiadnym miestom dvakrát). Kanalizácia je teda súvisláa neobsahuje žiadne cykly. Príklad toho, ako môže kanalizačná sieť vyzerať,nájdete pri príklade vstupu a výstupu.Služba v kanalizácii však nikoho príliš neteší, a tak by bolo dobre zistiť,

koľko najmenej strážcov zákona na túto službu treba.Súťažná úloha: Napíšte program, ktorý načíta mapu kanalizačnej siete a

popis toho, kde stoja mafiánske domy, a spočíta, koľko najmenej policajnýchhliadok stačí rozmiestniť, aby sa žiadni dvaja mafiáni k sebe cez kanalizáciunedostali.Pripomíname, že hliadky musia byť umiestnené pod niektorými z domov

(je jedno, či mafiánskych alebo nie), teda nie je dovolené umiestniť hliadku dostoky medzi dva domy.Ak umiestnime nejakú hliadku priamo pod dom mafiána, tento mafián sa

už cez kanalizáciu nedostane nikam.Formát vstupu: Prvý riadok vstupu obsahuje dve celé čísla N (3 ≤ N ≤

100 000) a P (2 ≤ P < N). Číslo N je počet domov, a zároveň teda početvýznamných miest v kanalizácii. Kanalizačný systém je tvorený presne N − 1stokami, pričom každá stoka priamo spája niektoré dve významné miesta (a tedadva domy). Domy sú očíslované číslami od 1 do N . Číslo P je počet domov,ktoré patria mafii.Nasleduje N − 1 riadkov, každý z nich obsahuje čísla jednej dvojice domov,

ktorá je spojená stokou.Každý z posledných P riadkov obsahuje jedno číslo domu patriaceho mafii.Formát výstupu: Vypíšte jeden riadok a v ňom jedno celé číslo – najmenší

počet hliadok, ktorý stačí umiestniť pod niektoré domy tak, aby sa medzi žiad-nymi dvoma mafiánskymi domami nedalo cez kanalizáciu prejsť.Príklad:

Page 43: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania celoštátneho kola kategórie A 41

Vstup

8 51 21 31 41 55 65 77 823467

Výstup

2

Jedna možnosť ako umiestniť dvehliadky je pod domy s číslami 1 a 5.Na obrázku prázdne krúžky predsta-vujú domy mafiánov.

1

234

5

6 7

8

A-III-5 Rybka Julka

Za horúcich letných dní voda v rybníku Blaťáku občas skoro vrie, a tak samalé rybky vždy utekajú ukryť do hlbokých chladných tôní. Len rybka Julka sadnes akosi pozabudla, a už začína byť v rybníku nepríjemne horúco. Pomôžtejej dostať sa čo najrýchlejšie do úkrytu!

Rybník Blaťák má tvar obdĺžnika a je rozdelený na R× S rovnako veľkýchštvorcových políčok. V tomto okamihu má políčko so súradnicami [r, s] teplotuTr,s rybích stupňov.Všetky časti rybníka sa ohrievajú rovnakým tempom: každú sekundu teplota

stúpne o jeden rybí stupeň.Julka znesie rozsah teplôt od t1 po t2 rybích stupňov (vrátane oboch hraníc).

V tomto okamihu sa nachádza na súradniciach [Jr, Js] a potrebovala by sadostať do svojho úkrytu, ktorý má súradnice [Cr, Cs]. Počas každej sekundy savie Julka presunúť na jedno zo štyroch stranou susediacich políčok, prípadne samôže rozhodnúť počkať na mieste. Vždy po tom, ako Julka vykoná jednu akciu,sa teplota rybníka zvýši.Julka sa nesmie cestou do cieľa opustiť rybník, nesmie sa prehriať a nesmie

ani prechladnúť. Môže sa teda pohybovať len po políčkach, ktorých aktuálna

Page 44: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

42 Zadania celoštátneho kola kategórie A

teplota T je z jej rozsahu, teda platí t1 ≤ T ≤ t2. Táto podmienka musí byťsplnená od okamihu, kedy Julka na políčko pripláva, až do okamihu, kým z nehoodpláva (medzitým teplota určite stúpla aspoň o stupeň). Výnimkou je cieľovépolíčko, kam môže vplávať bez ohľadu na jeho teplotu.

Súťažná úloha: Napíšte program, ktorý načíta popis celej situácie, zistí, vakom najkratšom čase sa vie Julka dostať do úkrytu a poradí jej jednu možnúoptimálnu cestu.

Formát vstupu: V prvom riadku vstupu sú štyri celé čísla R, S, t1 a t2oddelené medzerami.Číslo R udáva počet „riadkovÿ a S počet „stĺpcovÿ, na ktoré je rozdelený

rybník. Platí 1 ≤ R, S ≤ 1000. Čísla t1 a t2 udávajú Julkin teplotný interval,platí 0 ≤ t1 < t2 ≤ 106.

V druhom riadku vstupu sú štyri celé čísla Jr, Js, Cr a Cs – súradniceJulkinho štartu a cieľa. Platí 1 ≤ Jr, Cr ≤ R a 1 ≤ Js, Cs ≤ S.Môžete predpokladať, že cieľové políčko je rôzne od začiatočného.Rybník Blaťák je orientovaný tak, že na sever od políčka so súradnicami

[r, s] je políčko so súradnicami [r − 1, s], a na západ od [r, s] je [r, s− 1].

Posledných R riadkov vstupu popisuje začiatočné teploty políčok rybníka.Presnejšie, v riadku r+ 2 je S medzerami oddelených celých čísel: teploty Tr,1,Tr,2, . . . , Tr,s. Pre každé r, s platí 0 ≤ Tr,s ≤ 106.Môžete predpokladať, že na začiatku je teplota políčka, kde sa Julka práve

nachádza, pre ňu prijateľná.

Formát výstupu: Do výstupného súboru vypíšte jeden riadok a v ňompopis jednej optimálnej (teda najrýchlejšej) Julkinej cesty.Popis cesty sa skladá z niekoľkých pokynov, ktoré Julka postupne vykoná.

Pokyn je buď jeden znak S, J, V, Z, ktorý hovorí, že Julka sa má pohnúť smeromdo danej svetovej strany, alebo kladné celé číslo, ktoré hovorí, koľko sekúnd máJulka zostať čakať na aktuálnom políčku.Pokyny oddeľujte od seba jednou medzerou. Posledný pokyn musí byť pohyb.

Nikdy nesmú po sebe nasledovať dva pokyny na čakanie.Ak existuje viac rôznych optimálnych ciest, môžete si vybrať a vyššie uve-

deným spôsobom popísať ľubovoľnú z nich.Ak neexistuje žiadny spôsob ako Julku zachrániť, namiesto popisu cesty

vypíšte vetu „Chudinka Julka!ÿ (bez uvodzoviek).

Page 45: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Zadania celoštátneho kola kategórie A 43

Príklady:Vstup

4 3 10 202 2 4 39 7 130 18 151 15 192 3 0

Výstup

V S 1 Z Z 5 J J J V V

Toto je jedna z viacerých možnýchnajrýchlejších ciest. Ľubovoľná z nichby bola správnym riešením, na počtepríkazov nezáleží.

Vstup

2 3 20 301 1 1 325 13 2527 24 0

Výstup

Chudinka Julka!

Skôr ako sa niektoré z políčok, ktorémajú na začiatku teplotu 0 a 13, zo-hreje na dostatočnú teplotu, ostatnéprekročia Julkinu maximálnu teplotu.Najneskôr po siedmich sekundách chu-dinka Julka zahynie.

Page 46: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia domáceho kola kategórie A

A-I-1 Rozvoz pizze

Úlohu budeme riešiť „pažravoÿ (greedy). Najskôr si spočítame, koľko kusovakej veľkosti potrebujeme upiecť – teda koľko celých pízz, koľko kusov veľkosti5/6, atď. Toto vieme ľahko spraviť priamo pri načítaní vstupu.Celé pizze nerobia žiadne problémy. Podobne s kusmi veľkosti 5/6 je to

jednoduché – kvôli každému musíme upiecť jednu pizzu. Z tej nám 1/6 zvýši, azjavne nič nepokazíme, ak tieto kúsky použijeme na splnenie ďalších objednávok.Ak už objednávky na 1/6 nemáme, zvyšné šestiny musíme zahodiť.Pre kusy veľkosti 4/6 je situácia podobná. Na každý kus treba upiecť jednu

celú pizzu, zostane nám kus veľkosti 2/6. Ak máme málo objednávok na taktoveľké kusy, môžeme ho ešte rozkrojiť napoly a použiť na objednávky 1/6 pizze.(Zjavne je lepšie najskôr uspokojiť objednávky na 2/6 pizze.)Doteraz bolo všetko takmer jednoznačne určené, a teda nami navrhnuté

krájanie je zatiaľ optimálne. Zostáva nám vyriešiť situáciu, kedy všetky ešteneuspokojené objednávky sú na 3/6, 2/6 alebo 1/6 pizze.

♥: Objednávky 3/6 pizze vyriešime tak, že upečieme niekoľko pízz a každúrozkrojíme napoly. (Neskôr ukážeme, prečo je tento spôsob optimálny.) Ak bolpočet objednávok 3/6 pizze nepárny, zostala nám polovica pizze. Ak ešte mámeobjednávku na 2/6 pizze, odkrojíme z tejto polovice 2/6, zvyšok potom (aktreba) použijeme na objednávku 1/6 pizze. V opačnom prípade rozrežeme zo-stávajúcu polovicu na tri kúsky po 1/6 pizze.

♠: Už teda mohli zostať objednávky len na 2/6 a 1/6 pizze. Aby sme tieuspokojili, budeme piecť pizze a krájať ich na tretiny, až kým sa nám neminúobjednávky na 2/6 pizze. Zostávajúce objednávky na 1/6 pizze už vyriešimeľahko.

Prečo je tento postup optimálny?Dokážeme, že pri uspokojovaní objednávok na 3/6, 2/6 a 1/6 pizze nám

dokopy zvýšilo menej ako jedna celá pizza: Sú nasledujúce možnosti:

• Ak nám z časti ♥ nezostali žiadne zvyšky (teda počet objednaných polo-víc bol párny, alebo bolo dosť vhodných objednávok na 2/6 a 1/6), takvšetky zvyšné kusy vzniknú v časti ♠. Tam ale zostane nevyužitá len časťposlednej upečenej pizze.

Page 47: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia domáceho kola kategórie A 45

• Ak nám z časti ♥ zostala 1/6 pizze, znamená to, že už nezostali žiadneobjednávky na 1/6 pizze. Potom ale v časti ♠ vyrábame len časti veľké2/6, a teda nám zvýšia nanajvýš 4/6 pizze. (Z poslednej pizze sme vykrojiliaspoň jednu časť veľkosti 2/6.) Dokopy teda zvýši najviac 5/6 pizze.

• Ak nám z časti ♥ zostali 2/6 alebo 3/6 pizze, už nemáme žiadne objed-návky, a teda toto je celý zvyšok.

Pre objednávky na viac ako 3/6 pizze bolo optimálne delenie jednoznačneurčené. Ak sa to dalo, zvyšky sme použili na uspokojenie menších objednávok.Táto časť riešenia je teda zjavne optimálna. Zvyšné objednávky nebolo možnéuspokojiť upečením menšieho počtu pízz ako v našom riešení. (Ak by to šlo,muselo by pri našom riešení zvýšiť dosť odrezkov na celú pizzu, to ale nie jepravda.)Riešenie má lienárnu časovú a konštantnú pamäťovú zložitosť.

Listing programu:program pizza;varn : word; { Pocet objednavek }pozadavek : array[1..6] of longint; { Kolik dılu jake velikosti potrebuji? }napect : longint; { Kolik pizz je treba upect? }

procedure nacti;varF : Text;i, c : Integer;

beginfor i := 1 to 6 do pozadavek[i] := 0;assign(F, ’pizza.in’);reset(F);readln(F, n);for i := 1 to n do begin

readln(F, c);{ Vyrıdıme nejdrıve pocet celych pizz }pozadavek[6] := pozadavek[6] + c div 6;{ Nynı zvysıme pocet dılu prıslusne velikosti }c := c mod 6;if c > 0 then inc(pozadavek[c]);

end;close(F);

end;

procedure vypis;var F : text;begin

Page 48: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

46 Riešenia domáceho kola kategórie A

assign(F, ’pizza.out’);rewrite(F);writeln(F, napect);close(F);

end;

function min(a,b : longint) : longint;begin if a < b then min := a else min := b; end;

procedure spocti;begin{ Urcite potrebuji tolik pizz, kolik bylo objednavek na cele pizzy }napect := pozadavek[6];

{ Pro kazdy dıl velky 5/6 potrebuji jednu pizzu }napect := napect + pozadavek[5];

{ Dıly velke 5/6 lze doplnit pouze dıly velkymi 1/6 }pozadavek[1] := pozadavek[1] - min(pozadavek[5], pozadavek[1]);

{ Pro kazdy dıl velky 4/6 potrebuji jednu pizzu }napect := napect + pozadavek[4];

{ Doplnıme dıly velkymi 2/6 a 1/6 }if pozadavek[4] > pozadavek[2] then begin

pozadavek[4] := pozadavek[4] - pozadavek[2];pozadavek[2] := 0;pozadavek[1] := pozadavek[1] - min(2*pozadavek[4], pozadavek[1]);

end elsepozadavek[2] := pozadavek[2] - pozadavek[4];

{ Dıly velke 3/6=1/2 jdou kombinovat spolu }napect := napect + (pozadavek[3]+1) div 2;

{ Pokud je pocet polovin lichy, doplnıme je z 2/6 a 1/6 }if pozadavek[3] mod 2 > 0 then begin

if pozadavek[2] > 0 then begindec(pozadavek[2]);if pozadavek[1] > 0 thendec(pozadavek[1]);

end elsepozadavek[1] := pozadavek[1] - min(pozadavek[1], 3);

end;

{ Nynı pro zbyle dıly velke 2/6 = 1/3 }napect := napect + (pozadavek[2]+2) div 3;

{ Doplnıme prıpadnou 1 necelou pizzu z dılu 1/6 }if pozadavek[2] mod 3 > 0 then

pozadavek[1] := pozadavek[1] -

Page 49: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia domáceho kola kategórie A 47

min(pozadavek[1], 2*(3 - pozadavek[2] mod 3));

{ Nynı dıly velke 1/6 }napect := napect + (pozadavek[1]+5) div 6;

end;

beginnacti;spocti;vypis;

end.

A-I-2 Zasypané mesto

Najprv si popíšeme jednoduchšie riešenie, ktoré bude časovo a pamäťovonáročnejšie. V tomto riešení si budeme celú štvorcovú sieť uchovávať v pamätiako dvojrozmerné pole. Zaznamenáme do nej, pod ktorými políčkami je piesoka pod ktorými je kamenie. Naviac označíme všetky políčka ako nenavštívené(nenavštívené políčka budú zodpovedať políčkam miestností, ktoré sme doteraznenašli pri prechode sieťou).Štvorcovou sieťou budeme prechádzať postupne po riadkoch a hľadať po-

líčko s pieskom, ktoré je zatiaľ nenavštívené. Keď ho nájdeme, vieme, že smepráve objavili novú zasypanú miestnosť. Teraz prestaneme spracovávať políčkapostupne po riadkoch a namiesto toho teraz navštívíme všetky políčka novonájdenej miestnosti.Potom, čo navštívíme a spracujeme všetky políčka novej miestnosti, budeme

pokračovať v prechádzaní štvorcovej siete po riadkoch tam, kde sme skončili.Skončíme, až prejdeme celú sieť.Vynechali sme zatiaľ jednu dôležitú časť: Ako navštíviť všetky políčka práve

objavenej miestnosti? To urobíme pomocou prehľadávánia do šírky. Začneme vnovo nájdenom políčku, ktoré označíme ako navštívené. Potom budeme prechá-dzať jeho susedné políčka a každé také políčko, pod ktorým je piesok a ktoréje nenavštívené, označíme ako navštívené a spracujeme. Spracovaním políčkarozumieme to, že skontrolujeme, či nemá nejakého nenavštíveného suseda a akáno, tak tohoto suseda označíme ako navštíveného a pridáme ho na koniec zo-znamu políčok, ktoré musíme spracovať. Políčka sú teda spracovávané v poradí,v ktorom sme ich prvýkrát navštívili.Takéto riešenie má časovú i pamäťovú zložitost lineárne závislú od počtu

políčok siete, teda O(NM). Celá sieť sa nám ale vzhľadom k obmedzeniam zo

Page 50: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

48 Riešenia domáceho kola kategórie A

zadania úlohy do pamäte nevojde, a tak musíme navrhnúť pamäťovo úspornejšieriešenie.Zadanú sieť budeme spracovávať po riadkoch. V jednom kroku spracujeme

vždy jeden riadok, pričom si budeme pamätať predchádzajúci riadok. Potom,čo riadok spracujeme, stane sa z neho predchádzajúci riadok, načítame nový abudeme pokračovať, až kým nespracujeme všetky políčka siete.Teraz si popíšeme, ako vlastne budeme riadky spracovávať. Naším cieľom je,

aby všetky políčka s pieskom na spracovávanom riadku boli očíslované (ofar-bené) číslami 1 až b. Musia byť naviac očíslované tak, aby platilo: Dve políčkas pieskom majú tú istú farbu práve vtedy, ak z doteraz spracovaných riadkov(vrátane aktuálneho) o nich vieme, že patria do tej istej miestnosti.Celý algoritmus teda bude fungovať nasledovne. Na začiatku pridáme pred

celú sieť riadok políčok s kamením (ten je už spracovaný, keďže na ňom žiadnepolíčka s pieskom nie sú). Potom načítame ďalší riadok a pomocou predchádza-júceho riadku ho spracujeme – teda ofarbíme ho tak, aby sme dodržali vyššiestanovenú podmienku. (Podrobnejšie si tento krok popíšeme neskôr.)V priebehu spracúvania ďalšieho riadku spočítame, koľko na predchádzajú-

com riadku skončilo miestností (je to počet farieb, ktoré nesusedia so žiadnympieskovým políčkom na aktuálnom riadku) a tento počet pripočítame k celko-vému počtu objavených miestností.Takýto algoritmus je určite správny: každá miestnosť niekedy skončí, takže

ju určite započítame aspoň raz. Na druhej strane, kvôli tomu, ako ofarbujemespracovávané riadky, nikdy nemôžeme žiadnu miestnosť započítať viackrát nežraz. Zložitosť algoritmu bude M krát zložitosť spracovania jedného riadku.Ešte teda musíme vyriešiť spracovanie načítaného riadku. Predchádzajúci

riadok už máme ofarbený farbami 1 až b. Aktuálny riadok najprv ofarbíme far-bami od b+1 do c tak, že susedné pieskové políčka tohto riadku dostanú rovnakúfarbu. Potom využijeme informäcie z predchádzajúceho riadku: pokiaľ pieskovépolíčko spracovávaného riadku susedí s pieskovým políčkom predchádzajúcehoriadku, musíme „zlúčiťÿ ich farby.Pre každú farbu F si spravíme zoznam tých farieb, ktoré sa vyskytujú v

nejakej miestnosti, v ktorej je použitá aj farba F . Tieto zoznamy zostrojímejednoducho tak, že prejdeme celý riadok a vždy, keď nájdeme dvojicu farieb,ktoré treba zlúčiť, do zoznamu jednej zlučovanej farby pridáme druhú a naopak.Všimnite si ale, že takto zostrojené zoznamy nemusia priamo obsahovať

celé množiny „ekvivalentnýchÿ farieb. Ak sme napríklad zaznamenali, že trebazlúčiť farby 1 a 2 aj farby 2 a 3, znamená to, že všetky tri farby 1, 2 aj 3 trebanahradiť jednou novou. Naším cieľom bude teda pre jednu farbu nájsť všetky

Page 51: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia domáceho kola kategórie A 49

s ňou ekvivalentné farby. Všetky tieto farby potom prefarbíme na jednu novúfarbu.Na to použijeme vyššie popísaný postup prehľadávania do šírky: začneme

s počiatočnou farbou a označíme ju ako použitú (ostatné farby sú na začiatkuoznačené ako nepoužité). Potom budeme prechádzať jej zoznam farieb a ak na-razíme na farbu, ktorá je zatiaľ nepoužitá, pridáme ju do zoznamu farieb, ktorémusíme spracovať. Až celý proces skončí, budeme poznať všetky farby, ktorémajú so zadanou farbou spoločnú miestnosť. Takéto riešenie spracuje jeden ria-dok v čase O(N), a teda má časovú zložitosť O(MN) a pamäťovú O(N).Všimnime si teraz, že na spracovanie riadku si stačí pamätať intervaly tvo-

rené pieskom a ich farby. Teda nemusíme pracovať ani len s poľom dĺžky N ,ktoré by reprezentovalo predchádzajúci a nový riadok štvorcovej siete. Pokiaľpredchádzajúci riadok obsahuje K1 intervalov tvorených pieskom a nový K2 ta-kých intervalov, bude nám spracovanie týchto dvoch riadkov trvať O(K1+K2),pretože počet dvojíc pretínajúcích sa intervalov, teda tých, pre ktoré musímezlúčiť nejakú dvojicu farieb, je najviac K1 + K2 − 1. Samotné zlučovanie fa-rieb (prehľadávanie do šírky) je potom lineárne od počtu dvojíc farieb, ktoré jetreba zlúčiť. Celková časová zložitosť nášho algoritmu bude teda súčet hodnôtK1 a K2 cez všetky riadky, tj. O(K +M) (do odhadu časovej zložitosti mu-síme započítať aj počet riadkov pre prípad, že by štvorcová sieť obsahovala veľaprázdnych riadkov, tj. K by bylo oveľa menšie než M). Pamäťová zložitosť jenajviac lineárna od počtu políčok na jednom riadku, tj. O(N).

Listing programu:program mesto;type usek = record { datovy typ pro nacteny usek pısku }

barva, zacatek, konec: word;end;

const maxN = 50000;

type radek = record { datovy typ pro radek mapy }pocet_useku, pocet_barev: word;useky: array [1..maxN] of usek;

end;

var vstup, vystup: text; { vstupnı a vystupnı soubor }M, N: word; { rozmery mapy }L: longint; { pocet dosud nalezenych mıstnostı }predchozi_radek: radek; { radek, ktery byl uz zpracovan }novy_radek: radek; { radek, ktery je prave zpracovavan }

procedure inicializuj;begin

Page 52: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

50 Riešenia domáceho kola kategórie A

assign(vstup, ’mesto.in’);reset(vstup);readln(vstup, M, N, L);L := 0;predchozi_radek.pocet_useku := 0;predchozi_radek.pocet_barev := 0;

end;

type barva=record { datovy typ pro seznam barev, ktere majı byt slouceny }cislo: word;dalsi: ˆbarva;

end;

procedure sluc_barvy;{ provede sloucenı mıstnostı ulozenych v predchozi_radek a novy_radek;

zvysı L o jedna za kazdou mıstnost, ktera uz nepokracuje na novem radku }var ma_byt_slouceno: array[1..2*maxN] of ˆbarva;

{ seznam barev, ktere majı byt slouceny }vysledna_barva: array[1..2*maxN] of word;

{ barva, na kterou ma byt prebarveno }novy_pocet_barev: word; { novy pocet barev }seznam: array[1..2*maxN] of word; { seznam pro prohledavanı pri slucovanı }prvku_v_seznamu: word; { pocet prvku v seznamu }i, j: word; { nekolik pomocnych promennych }b:ˆbarva;

beginfor i := 1 to novy_radek.pocet_barev do ma_byt_slouceno[i] := nil;i := 1; j := 1;while (i <= predchozi_radek.pocet_useku) and (j <= novy_radek.pocet_useku) do

beginif (predchozi_radek.useky[i].zacatek < novy_radek.useky[j].konec) and

(novy_radek.useky[j].zacatek < predchozi_radek.useky[i].konec) thenbegin

new(b);bˆ.cislo := predchozi_radek.useky[i].barva;bˆ.dalsi := ma_byt_slouceno[novy_radek.useky[j].barva];ma_byt_slouceno[novy_radek.useky[j].barva] := b;new(b);bˆ.cislo := novy_radek.useky[j].barva;bˆ.dalsi := ma_byt_slouceno[predchozi_radek.useky[i].barva];ma_byt_slouceno[predchozi_radek.useky[i].barva] := b;

end;if predchozi_radek.useky[i].konec < novy_radek.useky[j].konecthen inc(i) else inc(j);

end;novy_pocet_barev := 0;for i := 1 to novy_radek.pocet_barev do vysledna_barva[i] := 0;for i := predchozi_radek.pocet_barev+1 to novy_radek.pocet_barev do

if vysledna_barva[i] = 0 thenbegin

Page 53: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia domáceho kola kategórie A 51

inc(novy_pocet_barev);vysledna_barva[i] := novy_pocet_barev;seznam[1] := i;prvku_v_seznamu := 1;j := 0;while j < prvku_v_seznamu do

begininc(j);b := ma_byt_slouceno[seznam[j]];while b<>nil do

beginif vysledna_barva[bˆ.cislo] = 0 thenbegin

vysledna_barva[bˆ.cislo] := novy_pocet_barev;inc(prvku_v_seznamu);seznam[prvku_v_seznamu] := bˆ.cislo;

end;b := bˆ.dalsi;

end;end;

end;for i := 1 to predchozi_radek.pocet_barev do

beginif vysledna_barva[i] = 0 then inc(L);while ma_byt_slouceno[i] <> nil dobegin

b := ma_byt_slouceno[i]ˆ.dalsi;dispose(ma_byt_slouceno[i]);ma_byt_slouceno[i] := b;

end;end;

novy_radek.pocet_barev := novy_pocet_barev;for i := 1 to novy_radek.pocet_useku do

novy_radek.useky[i].barva := vysledna_barva[novy_radek.useky[i].barva];predchozi_radek := novy_radek;

end;

procedure zpracuj_radek; { nacte radek a zavola proceduru sluc_barvy }var pisek, kameni: word; { nactena dvojice cısel }

sloupec: word; { pozice na nacıtanem radku }beginsloupec := 1;novy_radek.pocet_useku := 0;novy_radek.pocet_barev := predchozi_radek.pocet_barev;while sloupec <= N do

beginreadln(vstup, pisek, kameni);if pisek<>0 thenbegin

if (novy_radek.pocet_useku > 0) and

Page 54: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

52 Riešenia domáceho kola kategórie A

(sloupec = novy_radek.useky[novy_radek.pocet_useku].konec+1) thennovy_radek.useky[novy_radek.pocet_useku].konec :=

novy_radek.useky[novy_radek.pocet_useku].konec + pisekelsebegin

inc(novy_radek.pocet_useku);inc(novy_radek.pocet_barev);novy_radek.useky[novy_radek.pocet_useku].zacatek := sloupec;novy_radek.useky[novy_radek.pocet_useku].konec := sloupec+pisek-1;novy_radek.useky[novy_radek.pocet_useku].barva :=

novy_radek.pocet_barev;end;

end;sloupec := sloupec + pisek + kameni;

end;sluc_barvy;

end;procedure ukonci; { odsimuluje poslednı radek jako radek jen s kamenım }beginnovy_radek.pocet_useku := 0;sluc_barvy;

end;

procedure vypis; { vypıse pocet mıstnostı do vystupnıho souboru }beginassign(vystup, ’mesto.out’);rewrite(vystup);writeln(vystup, L);close(vystup);

end;

var i: word;begininicializuj;for i:=1 to M do zpracuj_radek;ukonci;vypis;

end.

A-I-3 Okružná jazda

Na úvod zavedieme označenie, ktoré sa štandardne používa v teórii grafov.Mapu Blatislavy budeme volať graf, križovatkám budeme hovoriť vrcholy a uli-ciam hrany. Hranu, ktorá vedie z vrcholu u do vrcholu v, budeme značiť uv.Počet vrcholov grafu označíme N a počet jeho hrán M .

Page 55: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia domáceho kola kategórie A 53

Vstupný stupeň vrcholu je počet hrán, ktoré do neho vchádzajú, teda počethrán, ktoré do neho vchádzajú. Podobne výstupný stupeň je počet hrán, ktoré zvrcholu vychádzajú. Zjavne nutnou podmienkou existencie riešenia našej úlohyje, aby sa v každom vrchole vstupný a výstupný stupeň rovnali. To isté inýmislovami: Ak máme nejaký vrchol, ktorý má rôzny vstupný a výstupný stupeň,môžeme si byť istí, že okružná cesta neexistuje.Hrany e a f na seba nadväzujú, ak e vchádza do vrcholu, z ktorého f vy-

chádza. Každú takúto dvojicu hrán budeme v tomto riešení označovať slovomprechod. Postupnosť navzájom rôznych hrán e1, . . . , ek takú, že pre všetky ihrana ei+1 nadväzuje na hranu ei, voláme ťah. Ťah, v ktorom navyše aj e1 nad-väzuje na ek, voláme uzavretý. Ťah, ktorý obsahuje všetky hrany grafu, volámeeulerovský.Našu úlohu (nájsť okružnú cestu) teraz môžeme formulovať takto: treba

nájsť uzavretý eulerovský ťah, ktorý neobsahuje žiadny zo zakázaných precho-dov.Naše riešenie bude pozostávať z dvoch krokov. Najskôr nájdeme ľubovoľný

eulerovský ťah, a ten potom upravíme tak, aby neobsahoval zakázané prechody.Ako zostrojiť eulerovský ťah:Ako začiatok si zjavne môžeme vybrať ľubovoľný vrchol. Teraz sa budeme

ľubovoľným spôsobom prechádzať po grafe, pričom farbíme hrany, ktorými smeuž išli a nejdeme tou istou hranou dvakrát. Časom sa dostaneme do situácie, žesa už nedá ísť ďalej. Keďže vždy pri prechode vrcholom ofarbíme jednu hranu,ktorá doň vchádza, a jednu, ktorá z neho vychádza, je len jedna možnosť, kdeskončíme: vo vrchole, v ktorom sme začali.Ak náš ťah prechádza všetkými hranami grafu, skončili sme. V opačnom

prípade ho ideme zlepšovať. Pozrime sa na graf tvorený len neofarbenými hra-nami. Opäť platí, že každý vrchol v ňommá rovnaký vstupný a výstupný stupeň.Nájdeme prvý vrchol v v tomto grafe, ktorý nie je izolovaný a leží na už zo-strojenom ťahu. (Ak takýto vrchol neexistuje, znamená to, že zadaný graf nie jesilne súvislý a okružná cesta neexistuje.) Opäť ľubovoľným prechádzaním sa poneofarbených hranách nájdeme nejaký ťah začínajúci aj končiaci vo v. Pôvodnezostrojený ťah vieme teraz predĺžiť: vo v ho rozpojíme a vložíme doň tento nový.Takto pokračujeme, kým nemáme ťah prechádzajúci všetkými hranami, alebonezistíme, že neexistuje.Tento algoritmus sa dá implementovať tak, aby mal časovú aj pamäťovú

zložitosť O(M +N), teda lineárnu od veľkosti grafu.Ako sa zbaviť zakázaných prechodov:

Page 56: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

54 Riešenia domáceho kola kategórie A

Najskôr vyriešime vrcholy, ktoré majú vstupný stupeň 1 a 2.Ak má nejaký vrchol vstupný stupeň 1, zakázaný prechod spôsobí, že sa

týmto vrcholom nedá prejsť, a teda okružná cesta neexistuje.Ak má nejaký vrchol vstupný stupeň 2, zakázaný prechod spôsobí, že je

práve jeden spôsob, ako cez tento vrchol prejsť. Ak teda do nášho vrcholu vvchádzajú hrany u1v a u2v, vychádzajú hrany vw1 a vw2, a prechod z u1vna vw2 je zakázaný, môžeme vrchol v a všetky štyri hrany z grafu vyhodiť anamiesto nich dať dve nové hrany u1w1 a u2w2.(V našej implementácii sme graf nemenili, len sme si dali pozor, aby sme

nepoužili zakázaný prechod: Ak pri zostrojovaní ťahu prídeme do v, dáme sipozor, aby sme odišli správnou hranou. Vo v nezačíname hľadanie nového ťahu.)

Predpokladajme teda, že náš graf obsahuje len vrcholy so vstupným stupňom3 a viac. Ak vyššie uvedený algoritmus zistil, že neexistuje žiaden eulerovskýťah, tým skôr neexistuje okružná cesta. Zostáva vyriešiť prípad, keď sme nejakýeulerovský ťah našli. Ukážeme, že za daných predpokladov tento ťah vždy viemeupraviť tak, aby nepoužíval zakázané prechody.Nech e1, . . . , em je uzavretý eulerovský ťah. Bez ujmy na všeobecnosti pred-

pokladajme, že prechod eme1 cez vrchol v je zakázaný. Keďže v má stupeň aspoň3, existujú ďalšie dve hrany ea a eb (a < b), ktoré do neho vchádzajú. Potomťah:

e1, e2, . . . , ea, eb+1, eb+2, . . . , em, ea+1, ea+2, . . . , eb

je tiež eulerovský, a navyše zakázaný prechod cez v nepoužíva.Opakovaním tohoto postupu postupne odstránime všetky zakázané prechody.

Takéto riešenie má časovú zložitosť O(ZM), kde Z je počet zakázaných precho-dov v ťahu nájdenom na začiatku. V najhoršom prípade teda máme časovúzložitosť O(NM).Vzorové riešenie:Namiesto toho, aby sme sa zlých prechodov zbavovali, budeme už prvý eule-

rovský ťah zostrojovať tak, aby sme sa im vyhli. To dosiahneme tak, že nebu-deme voliť hranu, ktorou vrchol opustíme, úplne náhodne.Náš algoritmus zaruči, že po každom predĺžení ťahu budú platiť nasledujúce

podmienky:

(1) Aktuálny ťah neobsahuje zakázané prechody.

(2) Ak aktuálny ťah aspoň raz prechádza cez vrchol v a zakázaný prechod cezv je ef , tak aspoň jedna z hrán e a f je už použitá.

Page 57: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia domáceho kola kategórie A 55

Ako predĺžiť ťah a neporušiť pri tom tieto podmienky?Keď prechádzame nejakým vrcholom, sú tri možnosti: Ak sme ním už išli,

zakázaný prechod už nevyrobíme. Ak sme ním ešte nešli a prichádzame prvouhranou jeho zakázaného prechodu, odídeme inou hranou ako druhou hranoujeho zakázaného prechodu. (Taká určite existuje.) Ak prichádzame ľubovoľnouinou hranou, odídeme druhou hranou zakázaného prechodu. V každom prípadesa nám podarilo zakázaný prechod „rozbiťÿ.Zostáva doriešiť, v ktorom vrchole a ako začať ťah predlžovať. Začneme

vo vrchole v, ktorý má vstupný stupeň aspoň 3, leží na existujúcom ťahu avedie z neho aspoň jedna nepoužitá hrana. Tam stačí použiť pravidlo takmeridentické tomu vyššie: ak hrana, ktorou v pôvodnom ťahu prídeme do v, je vjeho zakázanom prechode, odídeme tak, aby sme zakázaný prechod nevyrobili,inak odídeme prednostne tou, ktorá je v jeho zakázanom prechode. Rozmyslitesi, že takto vieme zaručiť, že ani na začiatku ani na konci vloženej časti ťahuzakázaný prechod nevznikne.Tento postup sa dá implementovať s časovou zložitosťou O(M +N).

Listing programu:program eulerovsky_tah;

const MAXN = 100;

type phrana = ˆhrana;hrana = record

z, k: integer; { hrana z vrcholu z do vrcholu k }pr, dal: phrana; { predchozı a nasledujıcı hrana v seznamu }tah: integer; { cıslo tahu, do nejz byla hrana pridana }tah_p, tah_d: phrana; { predchozı a nasledujıcı hrana v tahu }

end;

vrchol = recordstupen: integer; { stupen vrcholu }pouzite: hrana; { hlava seznamu pouzitych hran z vrcholu }nepouzite: hrana; { hlava seznamu nepouzitych hran }zak_z, zak_do: phrana; { prechod ze zak_z na zak_do je zakazany }

end;

var n: integer; { pocet vrcholu grafu }a: integer; { cıslo aktualnıho tahu }v: integer; { aktualnı vrchol }graf: array[1..MAXN] of vrchol;nr: integer;rozpracovane: array[1..MAXN] of integer; { seznam rozpracovanych vrcholu }nh: integer; { pocet hotovych vrcholu }

Page 58: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

56 Riešenia domáceho kola kategórie A

{ odebere hranu ze seznamu }procedure odeber (hrana: phrana);beginhranaˆ.dalˆ.pr := hranaˆ.pr;hranaˆ.prˆ.dal := hranaˆ.dal;hranaˆ.dal := nil;hranaˆ.pr := nil;

end;

{ prida hranu na zacatek seznamu }procedure pridej (var seznam: hrana; hrana: phrana);beginhranaˆ.dal := seznam.dal;hranaˆ.pr := @seznam;seznam.dal := hrana;hranaˆ.dalˆ.pr := hrana;

end;

{ vratı true, pokud je seznam prazdny }function prazdny (var seznam: hrana): boolean;begin prazdny := (seznam.dal = @seznam); end;

{ oznacı hranu danym cıslem, preradı ji do seznamu pouzitych hran, a prıpadnepriradı vrchol, z nejz hrana vede, do seznamu rozpracovanych hran }

procedure oznac_hranu (hrana: phrana; cislo: integer);var vrchol: integer;beginvrchol := hranaˆ.z;hranaˆ.tah := cislo;

odeber (hrana);if prazdny (graf[vrchol].nepouzite) then inc (nh);

if prazdny (graf[vrchol].pouzite) and (graf[vrchol].stupen <> 2) thenbegin

inc (nr);rozpracovane[nr] := vrchol;

end;pridej (graf[vrchol].pouzite, hrana);

end;

{ vratı true pokud je prechod z hrany Z na hranu K zakazany }function zakazano (z, k: phrana): boolean;var vrchol: integer;beginif z = nil then

zakazano := falseelse

beginvrchol := zˆ.k;

Page 59: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia domáceho kola kategórie A 57

if kˆ.z <> vrchol thenwriteln(’Chyba’);

zakazano := (graf[vrchol].zak_z = z) and (graf[vrchol].zak_do = k);end;

end;

{ vybere nepouzitou hranu z vrcholu, na kterou je povoleno prejıt z dane hrany }function vyber_hranu (vrchol: integer; hrana: phrana): phrana;var ah: phrana;beginah := graf[vrchol].nepouzite.dal;while (ah <> @graf[vrchol].nepouzite) and zakazano (hrana, ah) do

ah := ahˆ.dal;

if ah = @graf[vrchol].nepouzite then vyber_hranu := nilelse vyber_hranu := ah;

end;

{ oznacuje tah z nepouzitych hran, zacınajıcı hranou PRVNI, cıslem CISLO.Pokud PRVNI_TAH je true, tah muze skoncit, jakmile dorazı na hranu, kteranavaze na hranu PRVNI; jinak musı vyuzıt vsechny hrany z vrcholu PRVNIˆ.z }

procedure oznac_tah (prvni: phrana; cislo: integer; prvni_tah: boolean);var ahrana, prhrana: phrana;

avrchol: integer;beginprhrana := nil;ahrana := prvni;

repeatoznac_hranu (ahrana, cislo);if prhrana <> nil then

prhranaˆ.tah_d := ahrana;ahranaˆ.tah_p := prhrana;

prhrana := ahrana;avrchol := ahranaˆ.k;ahrana := vyber_hranu (avrchol, ahrana);

until (ahrana = nil)or (prvni_tah and (prhranaˆ.k = prvniˆ.z)

and not zakazano (prhrana, prvni));

prhranaˆ.tah_d := prvni;prvniˆ.tah_p := prhrana;if prvniˆ.z <> prhranaˆ.k then writeln(’Chyba’);

end;

{ pokud spojenı tahu pres hrany H1 a H2 nevytvorı zakazany prechod,spojı je a vratı true, jinak vratı false }

function spoj (h1, h2: phrana): boolean;var p1, p2: phrana;

Page 60: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

58 Riešenia domáceho kola kategórie A

beginp1 := h1ˆ.tah_p;p2 := h2ˆ.tah_p;if zakazano (p1, h2) or zakazano (p2, h1) then

spoj := falseelse

beginp1ˆ.tah_d := h2;h2ˆ.tah_p := p1;p2ˆ.tah_d := h1;h1ˆ.tah_p := p2;spoj := true;

end;end;

{ spojı A-ty tah v danem vrcholu s predchozımi }procedure spoj_tahy (vrchol: integer);var stara, nova, navic, ah: phrana;

t: boolean;beginah := graf[vrchol].pouzite.dal;stara := nil;nova := nil;navic := nil;while ah <> @graf[vrchol].pouzite do

beginif (ahˆ.tah = a) and (nova = nil) thennova := ah

else if (ahˆ.tah < a) and (stara = nil) thenstara := ah

elsenavic := ah;

ah := ahˆ.dal;end;

if not spoj (stara, nova) thenbegin

if navicˆ.tah = a thent := spoj (stara, navic)

elset := spoj (nova, navic);

if not t thenwriteln (’Chyba’);

end;end;

{ najde tah z nepouzitych hran zacınajıcı v danem vrcholu,a oznacı jeho hrany danym cıslem }

procedure najdi_tah (cislo, vrchol: integer);var prvni: phrana;begin

Page 61: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia domáceho kola kategórie A 59

prvni := vyber_hranu (vrchol, nil);oznac_tah (prvni, cislo, cislo = 1);

end;

{ najde hranu z vrcholu U do vrcholu V }function najdi_hranu (u, v: integer): phrana;var ah: phrana;beginah := graf[u].nepouzite.dal;while ahˆ.k <> v do ah := ahˆ.dal;najdi_hranu := ah;

end;

{ nacte graf ze souboru fin. Pokud graf obsahuje vrcholy stupne 1, vratı false }function nacti_graf (var fin: text): boolean;var m, i, u, v: integer;

h, d: phrana;beginreadln (fin, n, m);

for i := 1 to n dowith graf[i] do

beginstupen := 0;pouzite.dal := @pouzite;pouzite.pr := @pouzite;nepouzite.dal := @nepouzite;nepouzite.pr := @nepouzite;

end;

for i := 1 to m dobegin

readln (fin, u, v);new (h);hˆ.z := u;hˆ.k := v;hˆ.pr := nil;hˆ.dal := nil;hˆ.tah := 0;hˆ.tah_p := nil;hˆ.tah_d := nil;inc (graf[u].stupen);pridej (graf[u].nepouzite, h);

end;

for i := 1 to n dobegin

readln (fin, u, v);h := najdi_hranu (u, i);d := najdi_hranu (i, v);

Page 62: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

60 Riešenia domáceho kola kategórie A

graf[i].zak_z := h;graf[i].zak_do := d;{ hranu iv presuneme na zacatek seznamu, bude vzdy prvnı vybrana do tahu }odeber (d);pridej (graf[i].nepouzite, d);

end;

nacti_graf := true;for i := 1 to n do if graf[i].stupen < 2 then nacti_graf := false;

end;

{ vypıse eulerovsky tah v grafu do souboru FOUT }procedure vypis_tah (var fout: text);var prvni, ah: phrana;beginprvni := graf[1].pouzite.dal;ah := prvniˆ.tah_d;write (fout, prvniˆ.z);while ah <> prvni do begin write (fout, ’ ’, ahˆ.z); ah := ahˆ.tah_d; end;

end;

var fin, fout: text;

beginassign (fin, ’okruh.in’);reset (fin);assign (fout, ’okruh.out’);rewrite (fout);

if not nacti_graf (fin) thenbegin

writeln (fout, ’Okruzni jizda neexistuje.’);exit;

end;

a := 1;najdi_tah(a, 1);

while nr <> 0 do beginv := rozpracovane[nr];dec (nr);inc (a);najdi_tah (a, v);spoj_tahy (v);

end;

if nh = n then vypis_tah (fout)else writeln (fout, ’Okruzni jizda neexistuje.’);

end.

Page 63: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia domáceho kola kategórie A 61

A-I-4 Grafomat

Na nájdenie najkratšej cesty medzi vrcholmi v a w použijeme podobne akov Príklade 1 prehľadávanie do šírky. Začneme vo vrchole v. Aby sme vedeli„zostrojiťÿ cestu, bude si každý označený vrchol navyše pamätať hranu, poktorej doň značka prišla.Na rozdiel oproti klasickému prehľadávaniu sa nám môže stať, že vrchol

dostane naraz značku po viacerých hranách. V takom prípade si zapamätá ľu-bovoľnú jednu z nich.Akonáhle sa pri prehľadávaní dostaneme do cieľového vrcholu, budeme po-

stupovať späť po zapamätaných hranách a pritom značiť nájdenú cestu.

Takýto algoritmus už síce funguje, ale (obzvlášť ak je hľadaná cesta pomernekrátka v porovnaní s veľkosťou grafu) trávi zbytočne veľa času tým, že aj po tom,ako bol nájdený vrchol w a zostrojená cesta späť do v, prehľadávanie pokračujevo zvyšku grafu ďalej, až kým nenavštívi všetky dosiahnuteľné vrcholy.Potrebovali by sme vymyslieť spôsob, ako prehľadávanie zastaviť v okamihu,

keď sme už našli hľadanú cestu. To sa dá spraviť takto:Akonáhle prídeme pri označovaní cesty do vrcholu v, pošleme z neho ešte

jednu „vlnuÿ značiek. Tá bude mať za úlohu dobehnúť a zastaviť prvú vlnu.Pochopiteľne, aby to fungovalo, potrebovali by sme, aby naša druhá vlna po-stupovala rýchlejšie ako tá prvá, ktorá robí samotné prehľadávanie. My sícenevieme poslať druhú vlnu rýchlejšie ako vrchol za takt, tu je ale ľahká pomoc– stačí všetky ostatné časti programu pustiť dvakrát pomalšie.

Ako to bude vyzerať s časovou zložitosťou? Ak má hľadaná cesta l hrán, prvávlna príde do w po 2l krokoch. Po nasledujúcich 2l krokoch príde označovaniecesty späť do v. V tomto okamihu pustíme druhú vlnu. Tá teraz na prvú stráca4l taktov. Za každé nasledujúce 2 takty jeden takt straty dobehne, teda o 8ltaktov sa vlny stretnú a navzájom zrušia. Celkovo teda výpočet trvá 12l taktov,čiže je lineárny od dĺžky hľadanej cesty.

Listing programu:var x: 0..2; { vstupnı znacky }

y: 0..1 = 0; { vystupnı znacky }s: 0..2 = 0; { stav prohledavanı: 1=dorazila prvnı vlna, 2=uz i druha }b: 0..3 = 0; { kterou hranou jsme znacku prijali, je-li s>0 }p: 0..1 = 0; { pocıtadlo pro zpomalovanı }i: 1..3 = 1; { pomocna promenna }

Page 64: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

62 Riešenia domáceho kola kategórie A

beginp := 1-p;if (s=1) and ((S[1].s=2) or (S[2].s=2) or (S[3].s=2)) then

s := 2 { druha vlna bezı plnou rychlostı }else if p=1 then { ostatnı casti programu bezı zpomalene }

case s of0: begin

if x=1 then s := 1; { zacatek prvnı vlny }for i := 1 to 3 do { pokracovanı prvnı vlny }

if S[i].s = 1 then begin s := 1; b := i; end;if s=0 then stop; { stale se nic nedeje }

end;1: begin

if x=2 then y := 1 { prvnı vlna dorazila do cıle, jdeme zpet }for i := 1 to 3 do { zpetny pruchod }

if (S[i].y = 1) and (S[i].b = P[i]) then y := 1;if (y=1) and (x=1) then s := 2;

{ zpetny pruchod dorazil do pocatku }end;

2: stop;end;

end.

Page 65: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia domáceho kola kategórie B

B-I-1 Pestovanie mrkvičiek

Nech A = [x1, y1] a B = [x2, y2] sú body zo vstupu. Ak x1 = x2 aleboy1 = y2, úloha je ľahká.Teraz bez ujmy na všeobecnosti predpokladajme, že x1 < x2. Nech δx = x2−

x1 a δy = |y1−y2|. Nech C = [x3, y3] je bod, ktorý leží na úsečke spájajúcej body[x1, y1] a [x2, y2] (rôzny od A). Označme δ′x = x3 − x1 a δ′y = |y1 − y3|. Potomz podobnosti trojuholníkov ABB′ a ACC ′ (kde B′ = [x2, y1] a C ′ = [x3, y1])plynie:

δxδy=

δ′xδ′y

Nás zaujímajú také body C, pre ktoré δ′x a δ′y sú celé čísla. Chceme tedavedieť, koľko existuje takých celočíselných dvojíc a, b (a ≤ δx, b ≤ δy), žeab =

δxδy. Dva zlomky sa rovnajú práve vtedy, ak sa po ich úprave na základný

tvar rovnajú čitatele a menovatele. Ak d je najväčší spoločný deliteľ čísel δx aδy, tak zlomok δx

δymá základný tvar δx/d

δy/d.

Hľadáme teda také celé čísla a, b, ktoré sa po vydelení nejakým celým číslomk rovnajú δx/d a δy/d. To sú práve čísla (δx/d, δy/d), (2δx/d, 2δy/d), . . . , ((d−1)δx/d, (d − 1)δy/d), (δx, δy), čo je dokopy d dvojíc. Spolu s bodom A (ktorýsme na začiatku úvahy vylúčili) máme d+1 bodov s celočíselnými súradnicami.Číslo d vypočítame štandardným Euklidovým algoritmom. Všimnite si, že

v našej implementácií, ak jeden zo vstupných parametrov pre funkciu nsd je 0,tak výsledkom tejto funkcie je to druhé číslo, teda prípad x1 = x2, resp. y1 = y2nemusíme uvažovať ako špeciálny.

Listing programu:var x1,y1:longint;

x2,y2:longint;

function nsd(a,b:longint):longint;var c:longint;beginwhile (b<>0) do begin

c:=a mod b; a:=b; b:=c;end;

Page 66: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

64 Riešenia domáceho kola kategórie B

nsd:=a;end;

beginreadln(x1,y1);readln(x2,y2);writeln(nsd(abs(x2-x1),abs(y2-y1))+1);

end.

B-I-2 Hladný Samo

Táto úloha patri medzi tzv. ťažké úlohy v tom zmysle, že pre ňu ešte ni-kto nevymyslel efektívny algoritmus. Náše riešenie teda bude len skúšať všetkymožnosti.Ide teda o to, ako vygenerovať všetky možné podmnožiny potravín, pre

jednu podmnožinu overiť, či v nej nie sú 2 také potraviny, ktoré sa nemôžu jesťspolu a vybrať nejakú s najväčším počtom prvkov. Generovať všetky možnépodmnožiny sa dá rôzne. Pomerne jednoduché riešenie je postupne prechádzaťčísla 0, 1, . . . , 2N − 1, kde N je počet potravín, a reprezentovať ich binárnyzápis ako podmnožinu (i-ty bit hovorí, či tam i-ta potravina je alebo nie).Prehľadnejšie a efektívnejšie je generovať podmnožiny rekurzívne. Pre každú

potravinu sa rozhodneme, či ju zjeme alebo nie a pre obe možnosti sa rekurzívnespustíme na nasledujúcu potravinu. Výhoda je tá, že môžeme hneď overiť, čidanú potravinu môžeme v danom momente zjesť (zisťujeme, či potravina, ktorúchceme zjesť sa môže jesť spolu s doteraz zjedenými) a teda nemusíme to kon-trolovať, až keď máme vygenerovanú celú podmnožinu.Na konci už len zistíme, či sme našli väčšiu podmnožinu ako doteraz nájdenú.

Časová zložitosť tohto algoritmu je O(N2N ).

Listing programu:const MAXN=25;

var N,M,a,b,i,j:integer;mnoz:array[1..MAXN] of integer;maxmnoz:array[1..MAXN] of integer;dvojice:array [1..MAXN,1..MAXN] of boolean;poc,max:integer;

procedure skus(k:integer);var i:integer;

ok:boolean;begin

Page 67: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia domáceho kola kategórie B 65

if (k=N+1) then beginif (poc>max) then begin

max:=poc;for i:=1 to poc do maxmnoz[i]:=mnoz[i];

end;end else begin

skus(k+1);ok:=true;for i:=1 to poc do

if dvojice[k,mnoz[i]] thenok:=false;

if ok then begininc(poc);mnoz[poc]:=k;skus(k+1);dec(poc);

end;end;

end;

beginreadln(N,M);for i:=1 to N do for j:=1 to N do dvojice[i,j]:=false;

for i:=1 to M do beginreadln(a,b);dvojice[a,b]:=true; dvojice[b,a]:=true;

end;

skus(1);writeln(max);for i:=1 to max do write(maxmnoz[i],’ ’);writeln;

end.

B-I-3 Družstvá

Vezmime prvého hráča a bez ujmy na všeobecnosti ho priraďme do 1. druž-stva. Všetci hráči, ktorí nemôžu s ním hrať v družstve musia automaticky hraťv 2. družstve. Všetci, ktorí nemôžu hrať s týmito, musia hrať v 1. družstve, atď.Teraz, buď sa nám podarí hráčov rozdeliť (ostane nám ešte rozdeliť hráčov,

ktorí sú nezávislí od týchto), alebo budeme chcieť nejakého hráča dať do obochdružstiev. V takom prípade rozdelenie hráčov neexistuje. Funguje to len kvôlitomu, že máme len 2 družstvá. Ak by sme chceli zistiť, či sa dajú hráči rozdeliťdo 3 družstiev, už to nie je také jednoduché.

Page 68: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

66 Riešenia domáceho kola kategórie B

Rýchlosť algoritmu závisí od zvolenej reprezentácie vzťahov medzi hráčmi aod použitého systému priradzovania. Vzťahy si môžeme zapisovať do booleov-ského poľa N ×N , kde A[i, j] je true práve vtedy keď i a j nemôžu hrať spolu.Pri takejto reprezentácií je časová a pamäťová zložitosť O(N2).

Listing programu:const MAXN=100;

var N,M,a,b,i,j:integer;dvojice:array [1..MAXN,1..MAXN] of boolean;druzstvo:array [1..MAXN] of integer;nedasa:boolean;

procedure rozdel(v:integer);var i:integer;beginfor i:=1 to N do

if dvojice[v][i] then beginif druzstvo[i]=0 then begindruzstvo[i]:=3-druzstvo[v];rozdel(i);

end else if druzstvo[i]=druzstvo[v] thennedasa:=true;

end;end;

beginreadln(N,M);for i:=1 to N do for j:=1 to N do dvojice[i,j]:=false;for i:=1 to N do druzstvo[i]:=0;

for i:=1 to M do beginreadln(a,b);dvojice[a,b]:=true; dvojice[b,a]:=true;

end;

nedasa:=false;for i:=1 to N do

if druzstvo[i]=0 then begindruzstvo[i]:=1;rozdel(i);

end;

if nedasa thenwriteln(’Nie’)

else beginwriteln(’Ano’);for i:=1 to N do

if druzstvo[i]=1 then write(i,’ ’);

Page 69: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia domáceho kola kategórie B 67

writeln;end;

end.

B-I-4 Assembler

a) Vstup načítame na dvakrát. Pri prvom prechode si riadky očíslujeme ačísla riadkov, na ktorých sa vyskytujú návestia si zapamätáme. Pri druhomprechode programom si zapisujeme inštrukcie, pričom návestia nahradzu-jeme číslami riadkov, kde sa vyskytuje ich definícia.

Teraz už len odsimulujeme program na danom vstupe. Budeme si pamä-tať tzv. Instruction Pointer (IP), čo je číslo inštrukcie (v našom prípaderiadku), kde bude vykonávanie programu pokračovať. V prípade jednodu-chej inštrukcie len príslušne upravíme registre (a príznak Z). V prípadeinštrukcií jmp, jz a jnz len upravíme IP na príslušné číslo riadku.

b) Postupne budeme od registra R1 odčítavať hodnotu R2. To budeme robiťtak, že vždy od oboch odčítame 1 a ku R0 pričítame 1. Ak sa nám podaríodčítať celé R2, tak v R0 máme pôvodné R2, takže to len prelejeme do R2a pokračujeme znovu. Ak sa nám to nepodarí (tzn. ak budeme chcieť odR1 odčítať 1, ale už nebude z čoho), tak v R0 je zapísané, koľko sa námpodarilo odčítať, čo je akurát zvyšok po delení.

Na zisťovanie, či je už v R2 nula sme využili to, že inštrukcia dec tiežnastavuje príznak Z, ak po jej vykonaní je R2 = 0.

c1: test R1,R1jz koniecdec R1inc R0dec R2jz c2jmp c1

c2: test R0,R0jz c1dec R0inc R2jmp c2

koniec:

Page 70: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia krajského kola kategórie A

A-II-1 Stále ešte zasypané mesto

Očíslujme si možné zamerania: stredovek bude 1, starovek 2 a archeológia3. Nech a1, a2 a a3 sú počty prvákov s jednotlivými zameraniami, podobnenech b1, b2, b3 sú počty druhákov. Tieto počty si vieme spočítať pri načítavanívstupu.Začnime tým, že sa pozrieme na nejaké situácie, kedy riešenie nebude exis-

tovať. Všimnime si napríklad prvákov so zameraním 1. Každý z nich musí maťpartnera druháka so zameraním 2 alebo 3. Ak možných partnerov nemáme dosť(teda platí a1 > b2+b3), riešenie určite neexistuje. Ďalšie podmienky dostanemecyklickou obmenou tejto úvahy.Keďže platí a1 + a2 + a3 = b1 + b2 + b3 = N , vieme získané podmienky

upraviť do ekvivalentného tvaru: Aby existovalo riešenie, musí nutne platiť (♥)a1 + b1 ≤ N , a2 + b2 ≤ N a a3 + b3 ≤ N . V ďalšom texte ukážeme, že ak sútieto podmienky splnené, riešenie vždy existuje.Bez ujmy na všeobecnosti predpokladajme (⋆), že a1 ≥ a2 ≥ a3 a a3 ≤

min{b1, b2, b3}. (Inými slovami, vždy vieme dosiahnuť, aby tieto nerovnosti pla-tili, stačí vhodne očíslovať zamerania a prípadne vymeniť prvákov s druhákmi.)Rozoberieme teraz dva prípady.Nech platí a2 ≤ b1. Potom vytvoríme dvojice nasledovne: Bude a2 dvojíc

(prvák so zameraním 2)+(druhák so zameraním 1). Zostalo nám b1 − a2 dru-hákov so zameraním 1. Keďže vieme zo ♥, že b1 ≤ a2 + a3, je b1 − a2 ≤ a3.Zvyšných druhákov so zameraním 1 teda popárujeme s niektorými prvákmi sozameraním 3. Zostalo nám niekoľko (presnejšie a3−b1+a2) prvákov so zamera-ním 3. Keďže podľa našich predpokladov ⋆ je a3 ≤ b2, zjavne môžeme všetkýchtýchto prvákov popárovať s druhákmi so zameraním 2. A už sme vyhrali – ostalinám len prváci so zameraním 1 a druháci so zameraniami 2 a 3.Zostáva nám vyriešiť prípad keď a2 > b1. Opäť začneme dvojicami (prvák

so zameraním 2)+(druhák so zameraním 1), tentokrát ich bude b1 a zostanúnám nejakí nepriradení prváci so zameraním 2. Tých priradíme druhákom sozameraním 3 (podľa ♥ ich máme dosť). Podľa ⋆ máme aspoň toľko druhákov sozameraním 2 ako prvákov so zameraním 3, popárujeme ich, koľko ide. A opäťsme už vyhrali – ostali nám len prváci so zameraním 1 a druháci so zameraniami2 a 3.

Page 71: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia krajského kola kategórie A 69

Takto sme dostali algoritmus, ktorého časová zložitosť (až na načítanievstupu a výpis výstupu) aj pamäťová zložitosť je konštantná.

Listing programu:program mesto;var N:longint;

a,b:array[1..3] of longint;const spec:array[1..3] of string = (’starovek’,’stredovek’,’archeologia’);var rocnik_vymeneny:boolean; { pokial’ a[3]<b[3], vymenıme rocnıky }

subor:text;

procedure nacitaj;var subor:text;

i,rocnik:longint;s:string;

beginassign(subor,’mesto.in’);reset(subor);readln(subor,N);for i:=1 to 3 do begin a[i]:=0; b[i]:=0; end;for i:=1 to 2*N do begin

readln(subor,rocnik,s);if rocnik=1 then for i:=1 to 3 do if (s=’ ’+spec[i]) then inc(a[i]);if rocnik=2 then for i:=1 to 3 do if (s=’ ’+spec[i]) then inc(b[i]);

end;rocnik_vymeneny:=false;

end;

procedure zorad;var x,i,j:longint;

s:string;beginfor j:=1 to 3 do for i:=1 to j-1 do if a[i]<a[j] then begin

x:=a[i]; a[i]:=a[j]; a[j]:=x;x:=b[i]; b[i]:=b[j]; b[j]:=x;s:=spec[i]; spec[i]:=spec[j]; spec[j]:=s;

end;if b[3]<a[3] then begin

for i:=1 to 3 do begin x:=a[i]; a[i]:=b[i]; b[i]:=x; end;rocnik_vymeneny:=true;zorad;

end;end;

procedure vypis(pocet: longint; spec1,spec2: integer);{ vypıse “pocet“ dvojıc studentov so specializaciami spec1 a spec2 }

var x:integer;beginif rocnik_vymeneny then begin x:=spec1; spec1:=spec2; spec2:=x end;for x:=1 to pocet do writeln(subor,spec[spec1],’ ’,spec[spec2]);

Page 72: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

70 Riešenia krajského kola kategórie A

end;

beginnacitaj;zorad;assign(subor,’mesto.out’);rewrite(subor);if (a[1]+b[1]>N) or (a[2]+b[2]>N) or (a[3]+b[3]>N) then begin

writeln(subor,’Studenti sa nedaju rozdelit’ do dvojıc.’);end else

if (a[2]<=b[1]) then beginvypis(a[2],2,1);vypis(b[1]-a[2],3,1);vypis(a[3]-(b[1]-a[2]),3,2);vypis(a[1]-b[3],1,2);vypis(b[3],1,3);

end else beginvypis(b[1],2,1);vypis(a[2]-b[1],2,3);vypis(a[3],3,2);vypis(b[2]-a[3],1,2);vypis(b[3]-(a[2]-b[1]),1,3);

end;close(subor);

end.

A-II-2 Nová okružná jazda

Na úvod si zopakujme terminológiu z riešenia úlohy domáceho kola. MapuBlatislavy budeme volať graf, križovatky sú jeho vrcholy a ulice tvoria jehohrany. Počet vrcholov je N , počet hrán je M .Hranu medzi vrcholmi u a v značíme uv. Stupeň vrcholu je počet hrán, ktoré

z neho vychádzajú. Podľa zadania má náš graf všetky stupne vrcholov párne aväčšie ako 2. Hovoríme, že hrany e a f na seba nadväzujú, ak majú spoločnývrchol.Ťah je postupnosť vrcholov taká, že každé dva po sebe nasledujúce vrcholy sú

spojené hranou, pričom žiadna hrana nie je použitá viac ako jedenkrát. Uzavretýťah je ťah, ktorý začína a končí v tom istom vrchole. Eulerovský ťah je ťah, vktorom je každá hrana grafu použitá práve raz. Našou úlohou je teda nájsť vdanom grafe vhodný uzavretý eulerovský ťah.

Pre jednoduchšie vysvetlenie algoritmu špeciálne ošetríme vrcholy stupňa 4.Ľahko overíme, že keď zakážeme 3 prechody cez takýto vrchol, buď sa cez neho

Page 73: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia krajského kola kategórie A 71

nebude dať dvakrát prejsť, alebo bude jednoznačne určené, ako tieto prechodyvyzerajú. V prvom prípade hľadaný ťah neexistuje, v druhom môžeme prechodycez tento vrchol nahradiť dvoma hranami.Takto sa zbavíme všetkých vrcholov stupňa 4. Môžeme teda predpokladať,

že každý vrchol v zadanom grafe má stupeň aspoň 6. Ukážeme, že ak je takýtograf súvislý, tak v ňom hľadaný ťah existuje.Začneme tým, že graf rozložíme na niekoľko uzavretých ťahov, z ktorých žia-

den nebude obsahovať zakázaný prechod: V každom vrchole popárujeme hranydo dvojíc tak, aby žiadna dvojica netvorila zakázaný prechod. Keďže vrcholysú stupňa 6 a viac, toto zjavne vždy vieme spraviť. Tým už sme jednoznačneurčili nejakú množinu uzavretých ťahov, ktoré dokopy obsahujú každú hranugrafu práve raz. (Začneme ľubovoľnou hranou, a vždy, keď prídeme do vrcholu,odídeme hranou, ktorá s ňou tam bola v páre, až kým sa nevrátime ku hrane,kde sme začali.)Ak sa nám takto graf rozpadol na viac ako jeden ťah, musíme teraz ťahy po-

spájať do jedného. Zvolíme si ľubovoľný jeden ťah, nazveme ho hlavným ťahoma ostatné k nemu budeme pripájať.Ak sa niekedy ocitneme v situácii, že ešte máme nepripojené ťahy, ale žiadny

z nich nemá spoločný vrchol s hlavným ťahom, znamená to, že náš graf nie jesúvislý, a teda v ňom eulerovský ťah neexistuje. Nech teraz v je vrchol, ktorýmokrem hlavného ťahu prechádza ešte nejaký iný ťah. Ukážeme, ako tieto dvaťahy spojiť do jedného ťahu bez zakázaných prechodov.Nech vo v na seba (okrem iného) nadväzujú hrany e1 a e2 v hlavnom ťahu

a hrany e3 a e4 v nejakom inom ťahu. Ak sú prechody e1e3 a e2e4 povolené,môžeme tieto dva ťahy spojiť do jedného – nebude nadväzovať (e1 na e2) a (e3na e4), ale (e1 na e3) a (e2 na e4). Ukážeme teraz, že takéto dve dvojice hránurčite vieme nájsť. Rozoberieme dva prípady:

• Nech hlavný ťah prechádza cez v len raz, cez hrany e1 a e2. Potom vo vsú aspoň dva páry hrán, ktoré do hlavného ťahu nepatria. Označme dva znich e3e4 a e5e6. Všimnime si teraz nasledovné 4 dvojice prechodov: (e1e3a e2e4), (e1e4 a e2e3), (e1e5 a e2e6) a (e1e6 a e2e5). Keďže zakázané sú len3 prechody cez v, v niektorej z týchto 4 možností musia byť oba prechodypovolené. Táto možnosť teda hovorí, ako môžeme nejaký ďalší ťah pripojiťku hlavnému.

• Nech teda hlavný ťah prechádza cez v aspoň dvakrát. Zoberme dva takétoprechody a označme ich e3e4 a e5e6. Zoberme jeden prechod iného ťahu cez

Page 74: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

72 Riešenia krajského kola kategórie A

v a označme ho e1e2. Rovnakou úvahou ako v predchádzajúcom prípadezistíme, že niektorý zo štyroch spôsobov ako tieto dva ťahy spojiť nie jezakázaný.

Posledná otázka: S akou časovou zložitosťou vieme tento algoritmus imple-mentovať? V každom vrchole si budeme pamätať, ktoré hrany na seba nadväzujúa ktoré patria do hlavného ťahu. Ďalej budeme mať v každom vrchole zoznamhrán, ktoré do hlavného ťahu nepatria a nanajvýš dva prechody, ktoré do hlav-ného ťahu patria. Okrem toho budeme mať jeden globálny zoznam W vrcholov,cez ktoré ide hlavný ťah, ale ktoré ním ešte nie sú celé pokryté.Náš program bude fungovať nasledovne: Ak je W prázdny, skončili sme. V

opačnom prípade nech v je ľubovoľný vrchol zW . Pomocou pamätaných údajovvieme v konštantnom čase predĺžiť hlavný ťah vo vrchole v, a následne prejsťpo pridanej časti ťahu a upraviť informácie vo vrcholoch, cez ktoré prechádza.Tento prechod má časovú zložitosť lineárnu od veľkosti pridanej časti. Celýalgoritmus má teda časovú aj pamäťovú zložitosť lineárnu od veľkosti zadanéhografu.(Listing programu z priestorových dôvodov neuvádzame, v prípade záujmu

ho nájdete vo verzii, ktorá bude po skončení súťaže uverejnená na webe OI.)

A-II-3 Rozvoz pizze vo väčšom

Úlohu budeme riešiť metódou dynamického programovania. Postupne prekaždé i spočítame nasledujúce údaje:

• Počet pizzérií Pi, ktoré treba na pokrytie úsekov i až N .• Najväčší index Zi taký, že platí: Ak máme Pi pizzérií, tak nimi okremúsekov i až N vieme ešte pokryť aj úseky 1 až Zi.

• Ako pomocný údaj si ešte budeme pamätať počet úsekov Ui a súčet po-čtov zákazníkov Si, ktorých obsluhuje pri vyššie popísanom riešení „prváÿpizzéria, teda pizzéria obsluhujúca úseky od i ďalej.

Na začiatku vieme povedať, že PN = 1. V lineárnom čase nájdeme hodnotuZN (pridávame úseky, kým by súčet počtov zákazníkov nemal prekročiť K). UN

zatiaľ nebude zaujímavé, ale pre poriadok ho môžeme nastaviť na ZN + 1, SN

bude práve zistený súčet počtov zákazníkov.Teraz ideme nájsť všetky i, pre ktoré ešte platí, že Pi = 1. Nech teda už

poznáme hodnoty Pi+1 = 1, Zi+1 a Si+1. Ak Ai + Si+1 ≤ K, môžeme našej

Page 75: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia krajského kola kategórie A 73

zatiaľ jedinej pizzérii jednoducho pridať nový úsek a nič sa nemení. Bude tedaPi = 1, Zi = Zi+1, Ui = (N +1− i) +Zi a Si = Ai + Si+1. V opačnom prípadeuž nebudeme vedieť pokryť toľko úsekov „na začiatkuÿ, teda musíme postupnezmenšovať Zi (a adekvátne upravovať Ui a Si), až kým nebude Si ≤ K.Takto pokračujeme, kým Zi ≥ 0. Akonáhle sa dostaneme do situácie, že je

Zi = 0, a napriek tomu už je Si priveľké, znamená to, že budeme potrebovaťdruhú pizzériu. Od tohoto okamihu budeme nové hodnoty počítať nasledovne:Položíme Ui = Ui+1 + 1 a Si = Ai + Si+1, teda pridáme „prvejÿ pizzérii

nový úsek. Kým Si > K, zmenšujeme Ui o 1 a Si o Ai+Ui. Takto vlastne

„prvejÿ pizzérii priradíme najväčší možný počet úsekov začínajúci i-tym. A čoďalej? Zostáva nám pokryť úseky od i + Ui po N . Toto sme už ale riešili aoptimálne riešenie máme zapísané. Bude teda Pi = 1 + Pi+Ui

a Zi = Zi+Ui.

Spočítali sme teda hodnoty Pi a Zi. Potrebujeme ešte ukázať dve veci: akúmá ich výpočet časovú zložitosť a ako teraz zistíme optimálne riešenie pre celýkruh.Tvrdíme, že náš výpočet má časovú zložitosť O(N), teda lineárnu od počtu

úsekov. Prečo je tomu tak? Môže sa síce stať, že pri výpočte niektorej konkrétnejhodnoty Ui budeme musieť prvej pizzérii postupne zobrať veľa úsekov, všimnimesi ale, že dokopy za celý výpočet každý úsek prvej pizzérii zoberieme najviacjedenkrát. Preto na výpočet všetkých hodnôt Ui a Si dokopy nám stačí časO(N). Výpočet hodnôt Pi a Zi nám zjavne zložitosť nepokazí.A ako teda nájsť optimálne riešenie pôvodnej úlohy? Predstavme si takéto

optimálne riešenie. Ak nejaká pizzéria obsluhuje úseky 1 aj N , na chvíľu juzrušíme. Teraz nech x je číslo najmenšieho obsluhovaného úseku. Potom zjavnePx je počet pizzérií v optimálnom riešení. A môžeme si všimnúť, že Zx ≥ x− 1,lebo posledná použitá pizzéria musí pokryť aj prvých x− 1 úsekov.My ale hodnotu x nepoznáme. Nič nám však nebráni v čase O(N) vyskúšať

všetky možné x, pre ktoré Zx ≥ x− 1, a zobrať minimum z hodnôt Px.

Listing programu:program pizza;const maxN=100000;var A: array[1..maxN] of longint;

N, K: longint;Pocet, Kam, Dalsi: array[1..maxN] of longint;{ Pocet[i] je minimalnı pocet intervalu nutnych k pokrytı useku od i do N;

tyto intervaly navıc pokryjı vsechny useky od i do Kam[i];v optimalnım pokrytı zacına po intervalu se zacatkem idalsı interval na Dalsi[i] }

soubor: text;

Page 76: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

74 Riešenia krajského kola kategórie A

i, j: longint;soucet, optimum: longint;

beginassign(soubor,’pizza.in’);reset(soubor);readln(soubor,N,K);for i:=1 to N do readln(soubor,A[i]);close(soubor);{ nejdrıve inicializujeme konec pole }{ j bude nejvetsı cıslo takove, ze soucet A[1] az A[j] je mensı nebo roven K }j:=1; soucet:=A[1];while (j<=N) and (soucet+A[j]<=K) do begin

soucet:=soucet+A[j];inc(j);

end;if j=N+1 then begin

{ stacı jedna pizzerie }assign(soubor,’pizza.out’);rewrite(soubor);writeln(soubor,1);writeln(soubor,1,’ ’,N);close(soubor);exit

end;{ nynı spocıtame hodnoty na konci pole }i:=N;{ i bude index prvku, jehoz hodnoty nynı pocıtame }while j>0 do begin

if soucet+A[i]>K then beginsoucet:=soucet-A[j];dec(j);continue;

end;Pocet[i]:=1;Kam[i]:=j;Dalsi[i]:=j+1;soucet:=soucet+A[i];dec(i);

end;while soucet+A[i]<=K do begin

Pocet[i]:=1;Kam[i]:=0;Dalsi[i]:=N+1;soucet:=soucet+A[i];dec(i);

end;{ i je stale index pocıtaneho prvku a j je maximalnı

index takovy, ze soucet A[i+1] az A[j] je mensı nebo roven K }j:=N;

Page 77: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia krajského kola kategórie A 75

while i>0 do beginif soucet+A[i]>K then begin

soucet:=soucet-A[j];dec(j);continue;

end;Pocet[i]:=Pocet[j+1]+1;Kam[i]:=Kam[j+1];Dalsi[i]:=j+1;soucet:=soucet+A[i];dec(i);

end;{ zbyva nalezt optimum }optimum:=Pocet[1]; j:=1;for i:=1 to N do

if (Kam[i]+1>=i) and (optimum>Pocet[i]) then beginoptimum:=Pocet[i];j:=i;

end;assign(soubor,’pizza.out’);rewrite(soubor);writeln(soubor,optimum);i:=j;while Pocet[j]>1 do begin

writeln(soubor,j,’ ’,Dalsi[j]-1);j:=Dalsi[j];

end;if i=1 then

writeln(soubor,j,’ ’,N)else

writeln(soubor,j,’ ’,i-1);close(soubor);

end.

A-II-4 Grafomat loví zver

Zaoberajme sa najskôr jednoduchším problémom. Majme v grafe dva vrcholyl a p, ktoré sú spojené cestou. Chceme ich zosynchronizovať, teda spôsobiť, abynejaká udalosť („zazretie zvieraťaÿ) v p spôsobila, že časom tá istá udalosť(„výstrelÿ) nastane v oboch naraz.Toto vieme dosiahnuť napr. trikom s rôzne rýchlymi signálmi, ktorý sme si

ukázali v riešeniach domáceho kola. Vyšleme z p do l dva signály, z ktorýchjeden ide polovičnou rýchlosťou ako druhý. Keď rýchlejší príde do l, odrazí sa aputuje naspäť. V okamihu, keď sa rýchlejší signál vráti do p, príde do l pomalšísignál. V programe to vyzerá takto:

Page 78: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

76 Riešenia krajského kola kategórie A

Listing programu:var x: 0..3; { 1=l, 2=p, 3=p behem vypoctu, 0=ostatnı }

y: 0..1 = 0; { vystup }a, aa, b: 0..3 = 0; { signaly a kolik taktu zbyva do jejich predanı dal }

begin{ Na pocatku vysleme signaly A a B. }if x=2 then begin x:=3; a:=2; b:=3; end;

{ Signal A putuje vlevo rychlostı 1, vlevo se odrazı a je z nej A’. }if a>0 then dec(a);if S[1].a=1 then a:=1;if (x=1) and (a>0) then begin a:=0; aa:=2; end;

{ Signal A’ putuje vpravo rychlostı 1. }if aa>0 then dec(aa);if S[2].aa=1 then aa:=1;

{ Signal B putuje vlevo rychlostı 1/2. }if b>0 then dec(b);if S[1].b=1 then b:=2;

{ Kdyz A’ a B doputujı na protilehly konec, vypalıme. }if (x=1) and (b>0) then begin b:=0; y:=1; end;if (x=3) and (aa>0) then begin aa:=0; y:=1; end;

{ Nenı-li co delat, koncıme. }if (a=0) and (aa=0) and (b=0) then stop;

end.

Keď vieme synchronizovať dvojice vrcholov, môžeme väčší počet vrcholovzosynchronizovať použitím metódy rozdeľ a panuj. Predstavme si, že máme 2k+1 vrcholov v rade, pričom najľavejší z nich je na začiatku označený ako začiatokintervalu a najpravejší ako zarážka za koncom intervalu. Ako zosynchronizovaťvšetky vrcholy okrem najpravejšieho?Pre k = 1 máme zosynchronizovať dva vrcholy, a to už vieme spraviť. Pre

väčšie k rozdelíme náš interval na dve rovnako veľké polovice, zosynchronizu-jeme ich najľavejšie vrcholy, a potom paralelne zosynchronizujeme každú po-lovicu zvlášť. Ako rozdeliť interval na polovicu, keď nepoznáme jeho dĺžku?Opäť použijeme dva signály, tentokrát pomalší pôjde tretinovou rýchlosťou.Kým rýchlejší signál prejde na koniec, odrazí sa a vráti sa do polovice, pomalšípráve dorazí do polovice intervalu. Keď sa teda signály stretnú, našli sme stredintervalu.Majme teraz N = 2k vrcholov na kružnici. Tam to bude fungovať úplne

rovnako, len vrchol, ktorý „zazrel zverÿ, bude v prvom kole slúžiť aj ako ľavýokraj intervalu, aj ako zarážka za pravým okrajom.

Page 79: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia krajského kola kategórie A 77

Každá iterácia tohoto algoritmu trvá lineárne dlho od dĺžky intervalov, ktorépráve synchronizujeme. Celková časová zložitosť teda je O(N + N/2 + N/4 +· · ·+ 1) = O(N).

Listing programu:var x: 0..3; { 1=pocatek, 2=okraj, 3=stred intervalu }

y: 0..1 = 0; { vystrel }a, aa, b, c, cc, d: 0..3 = 0; { signaly a kolik taktu zbyva do predanı dal }

begin{ Trivialnı vstup => vypalıme hned. }if (x=1) and (S[1].x=1) then begin y:=1; stop; end;

{ Na pocatku vysleme signaly C a D. }if x=1 then begin x:=2; d:=3; end;if S[2].x=1 then c:=2;

{ Signal C putuje vpravo rychlostı 1, vpravo se odrazı jako C’. }if c>0 then dec(c);if S[2].c=1 then c:=1;if (x=2) and (c>0) then begin c:=0; cc:=2; end;

{ Signal C’ putuje vlevo rychlostı 1. }if cc>0 then dec(cc);if S[1].cc=1 then cc:=1;

{ Signal D putuje vpravo rychlostı 1/3. }if d>0 then dec(d);if S[2].d=1 then d:=3;

{ Kdyz se C’ a D potkajı, mame stred. Vysleme z nej A a B. }if (x=0) and (cc>0) and (d>0) then begin cc:=0; d:=0; x:=3; a:=2; b:=3; end;

{ Signal A putuje vlevo rychlostı 1, vlevo se odrazı a je z nej A’. }if a>0 then dec(a);if S[1].a=1 then a:=1;if (x=2) and (a>0) then begin a:=0; aa:=2; end;

{ Signal A’ putuje vpravo rychlostı 1. }if aa>0 then dec(aa);if S[2].aa=1 then aa:=1;

{ Signal B putuje vlevo rychlostı 1/2. }if b>0 then dec(b);if S[1].b=1 then b:=2;

{ Kdyz A’ doputuje zpet do stredu a B doleva, spustıme se v obou polovinach. }if (x=2) and (b>0) then begin b:=0; x:=1; end;if (x=3) and (aa>0) then begin aa:=0; x:=1; end;

Page 80: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

78 Riešenia krajského kola kategórie A

{ Nenı-li co delat, koncıme. }if (a=0) and (aa=0) and (b=0) and (c=0) and (cc=0) and (d=0) and (x<>1)

then stop;end.

Poznámka: Riešenie pre všeobecnú kružnicu nie je o toľko ťažšie. Keď delímena polovicu interval nepárnej dĺžky, to, že je nepárnej dĺžky, zistíme tak, že sanám signály v strede nestretnú presne. V takomto prípade stredný vrchol vyne-cháme a nebudeme ho synchronizovať. Skončíme s tým, že zosynchronizujemenejakú množinu vrcholov, pričom žiadne dva nezosynchronizované spolu nesu-sedia. Stačí teda, aby si namiesto „strieľajÿ zosynchronizované vrcholy nastavilinovú značku „zamierÿ. A v nasledujúcom takte vystrelí každý, kto vidí značku„zamierÿ u seba alebo niektorého suseda.

Page 81: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia krajského kola kategórie B

B-II-1 Kerfúr ten je lacnejší

Pokúsime sa zostrojiť nejaké poradie supermarketov, ktoré by zodpovedalovšetkým reklamám. Ak sa nám to podarí, bude výstup ANO, naopak, ak zistíme,že sa to nedá, bude výstup NIE.Majme teda niekoľko supermarketov. Rozdeľme si ich na dve kôpky. Na

prvú dáme tie, o ktorých nik iný netvrdí, že je od nich lacnejší. Na druhej tedasamozrejme zostanú tie, od ktorých poznáme aspoň jeden lacnejší.Pokiaľ je prvá kôpka prázdna, hľadané usporiadanie zjavne neexistuje – žia-

den zo supermarketov nemôže byť najlacnejší.(Rozmyslite si, že ak táto situácia nastala, znamená to, že na vstupe sme

dostali cyklus – postupnosť supermarketov s1, . . . , sk takú, že pre každé i je silacnejší ako si+1, a navyše aj sk má byť lacnejší ako s1. Keby bolo treba, takýtocyklus nájdeme ľahko: začneme ľubovoľným supermarketom a vždy prejdemena nejaký, ktorý má od práve spracúvaného byť lacnejší, až kým sa nám nejakýsupermarket v takto získanej postupnosti nezopakuje.)Pokiaľ je na prvej kôpke aspoň jeden supermarket, môžeme hociktorý z

týchto supermarketov vyhlásiť za najlacnejší. Rozmyslite si, že tým naozaj ničnemôžeme pokaziť.Vyberieme si teda ľubovoľný supermarket z prvej kôpky, prehlásime ho za

najlacnejší a úplne naň zabudneme. A čo sme takto dostali? Tú istú úlohu,len máme o jeden supermarket menej. Rovnakým postupom teda pokračujemeďalej, a sú len dve možnosti: buď časom narazíme na cyklus (a zistíme, že riešenieneexistuje), alebo sa nám časom všetky supermarkety minú a máme hotové celéporadie.

Ako to šikovne naprogramovať? Pre každý supermarket si budeme pamätať,koľko supermarketov má byť od neho lacnejších a tiež zoznam všetkých, ktorémajú byť od neho drahšie. Okrem toho si budeme v jednom poli pamätať číslatých supermarketov, ktoré už od seba nemajú mať nikoho lacnejšieho.Výber jedného supermarketu bude prebiehať nasledovne: Pozrieme sa do

poľa s kandidátmi a vyberieme posledného z nich. Teraz ho potrebujeme odstrá-niť. Prejdeme všetky supermarkety, ktoré majú od neho byť väčšie. Každému znich zmenšíme počítadlo menších o jedna, a ak kleslo na nulu, pridáme ho nakoniec poľa kandidátov.

Page 82: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

80 Riešenia krajského kola kategórie B

Spracovanie jedného supermarketu teda trvá lineárne dlho v závislosti odpočtu reklám, ktoré ho chvália. Spracovanie všetkých supermarketov dokopybude teda trvať lineárne dlho od počtu všetkých reklám. Lepšie to ani nejde,lebo rádovo rovnaký čas nám zoberie už len načítanie vstupu.

Listing programu:program reklamy;var mensich, vacsich, kandidati : array[1..1000] of longint;

vacsie : array[1..1000,1..1000] of longint;N, M, i, j, x, y, kandidatov, teraz : longint;

beginreadln(N,M);for i:=1 to N do begin mensich[i]:=0; vacsich[i]:=0; end;for i:=1 to M do begin

readln(x,y);inc(vacsich[x]); inc(mensich[y]);vacsie[ x ][ vacsich[x] ] := y;

end;{ inicializujeme pole kandidatov }kandidatov := 0;for i:=1 to N do if mensich[i]=0 then begin

inc(kandidatov);kandidati[ kandidatov ]:=i;

end;{ N-krat skusime vybrat najlacnejsi supermarket }for i:=1 to N do begin

{ ak nemame ziadneho kandidata, zle je }if kandidatov=0 then begin writeln(’NIE’); halt; end;{ ak mame, odstranime ho }teraz := kandidati[ kandidatov ];dec(kandidatov);for j:=1 to vacsich[teraz] do begin

x := vacsie[teraz][j];dec(mensich[x]);if mensich[x]=0 then begin { mame noveho kandidata }

inc(kandidatov);kandidati[kandidatov] := x;

end;end;

end;writeln(’ANO’);

end.

Poznámka. Úloha sa dá preformulovať do jazyka teórie grafov. Jednotlivésupermarkety budú predstavovať vrcholy grafu, informáciu „je lacnejšíÿ si za-značíme ako orientovanú hranu. Hľadané usporiadanie supermarketov sa volá

Page 83: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia krajského kola kategórie B 81

topologické usporiadanie vrcholov grafu. Ukázali sme, že takéto usporiadanieexistuje práve vtedy, ak je graf zodpovedajúci zadaniu acyklický.

B-II-2 Televízna súťaž

Keďže čísla sú z príliš veľkého rozsahu na to, aby sme si mohli značiť v poli,ktoré sme koľkokrát videli, budeme si musieť pomôcť ináč.Jedným možným riešením je čísla, ktoré dostaneme zadané na vstupe, uložiť

do poľa a toto pole utriediť. Ak to spravíme použitím šikovného triediacehoalgoritmu (napríklad QuickSort), budeme na utriedenie čísel potrebovať rádovoN logN operácií. Keď už máme čísla utriedené, stačí raz prejsť poľom a spočítaťsi, ktorá hodnota sa v ňom koľkokrát vyskytuje. (Vľimnite si, že po utriedeníbudú všetky výskyty konkrétneho čísla tvoriť v poli súvislý úsek.)

Listing programu:program sutaz1;var a : array[1..10047] of longint;

n,i,kandidat,pkand,pteraz : longint;

procedure QuickSort(zaciatok, koniec: longint);{ utriedi cisla, ktore su v poli A na poziciach zaciatok .. koniec }

var pivot, malych, strednych, i, pom : longint;begin

if (koniec <= zaciatok) then exit; { ak je usek kratky, skonci }pivot := A[zaciatok]; { vyber jeden z prvkov ako pivota }malych := 0; { presunieme “male“ prvky na zaciatok }for i:=zaciatok to koniec do

if (A[i] < pivot) then beginpom:=A[i]; A[i]:=A[zaciatok+malych]; A[zaciatok+malych]:=pom;Inc(malych);

end;{ a mame “male“ prvky na poziciach zaciatok .. zaciatok+malych-1 }

strednych := malych; { za ne presunieme prvky rovne pivotu }for i:=zaciatok+malych to koniec do

if (A[i] = pivot) then beginpom:=A[i]; A[i]:=A[zaciatok+strednych]; A[zaciatok+strednych]:=pom;Inc(strednych);

end; { a mame prvky rovne pivotu na poziciachzaciatok+malych .. zaciatok+strednych-1 }

{ teraz samostatne utriedime usek “malych“ prvkov ... }QuickSort(zaciatok, zaciatok+malych-1);QuickSort(zaciatok+strednych, koniec); { ... a usek “velkych“ prvkov }

end;

begin

Page 84: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

82 Riešenia krajského kola kategórie B

read(n);for i:=1 to n do read(a[i]);QuickSort(1,n);{ v premennej “kandidat“ je doteraz najcastejsi prvok, v “pkand“ je

pocet jeho vyskytov, v “pteraz“ je pocet vyskytov aktualneho prvku }kandidat:=-1; pkand:=0; pteraz:=0;for i:=1 to n do begin

if (i=1) or (a[i-1]=a[i]) then inc(pteraz) else pteraz:=1;if (pteraz > pkand) then begin kandidat:=a[i]; pkand:=pteraz; end;

end;writeln(kandidat);

end.

Existujú však ešte lepšie riešenia, založené na metóde hašovania. Predstavmesi, že nám z neba spadla funkcia f , ktorá každému číslu zo vstupu priradí číslopovedzme z intervalu od 0 do N − 1. Navyše chceme, aby výstupné hodnoty fboli približne rovnako pravdepodobné. (Teda ak vypočítame hodnotu f pre veľanáhodných vstupov, dostaneme každý výsledok približne rovnako veľa krát.)Ako by nám takáto funkcia pomohla pri riešení úlohy? Predstavme si, že

máme N vedier označených číslami od 0 do N − 1. Pre každé číslo x zo vstupuspočítame hodnotu f(x) a do toho vedra x hodíme. Potom stačí každé vedrospracovať samostatne.Získali sme tým niečo? Na vstupe bolo najviac N rôznych hodnôt, preto

môžeme očakávať, že v priemere bude v každom vedre len jedna hodnota. Vedrá,v ktorých skončila len jedna hodnota, ľahko spracujeme v konštantnom čase. Prekaždé z ostatných vedier môžeme napríklad použiť vyššie popísaný algoritmus– čísla utriedime a raz prejdeme.Samozrejme, najhorší možný prípad je, že na vstupe je N rôznych čísel, ale

všetky skončia v tom istom vedre. Takýto prípad je ale veľmi nepravdepodobný.V priemernom prípade má náš algoritmus časovú zložitosť lineárnu od počtučísel na vstupe, v najhoršom prípade bude jeho časová zložitosť naďalej úmernáčasovej zložitosti triedenia, teda O(N logN).Posledná otázka: odkiaľ vziať funkciu f? Môžeme pre jednoduchosť uvažovať

funkciu f(x) = x mod N . (V praxi sa používajú zložitejšie hašovacie funkcie.)

Listing programu:program sutaz2;type pzaznam = ˆtzaznam;

tzaznam = record next : pzaznam; hodnota : longint; end;var vedra : array[0..10047] of pzaznam;

prve : array[0..10047] of longint;pocet : array[0..10047] of longint;N,i,x : longint;

Page 85: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia krajského kola kategórie B 83

kandidat,pkand : longint;

{ pridaj(kam,co) prida hodnotu “co“ na zaciatok zoznamu “kam“ }procedure pridaj(kam : pzaznam; co : longint);var tmp : pzaznam;begin getmem(tmp,sizeof(tzaznam)); tmpˆ.hodnota:=co; tmpˆ.next:=kam; end;

{ hashovacia funkcia f }function f(x : longint) : longint; begin f:=x mod N; end;

beginread(N);for i:=0 to n-1 do begin pocet[i]:=0; vedra[i]:=nil; end;for i:=1 to n do begin

read(x);if pocet[f(x)]=0 then begin

prve[f(x)]:=x; pocet[f(x)]:=1;end else begin

if prve[f(x)]=x then inc(pocet[f(x)]) else pridaj( vedra[ f(x) ], x );end;

end;kandidat:=-1; pkand:=0;for i:=0 to n-1 do begin { spracujeme vedro i }

if pocet[i]>pkand then begin pkand:=pocet[i]; kandidat:=prve[i]; end;if vedra[i]<>nil then begin

{ ... prepiseme zvysny obsah vedra do pola ... }{ ... pouzijeme na pole predchadzajuci program ... }

end;end;writeln(kandidat);

end.

B-II-3 Kartári

Lackov balíček kariet zodpovedá dátovej štruktúre známejšej pod menomfronta. Môžeme si ho predstaviť ako takú dlhú rúru, do ktorej jedným koncomkarty vkladáme a druhým koncom z nej v tom istom poradí vypadávajú.Pomalé riešenie je pamätať si karty v poli a pri každom výbere ich o jedno

posunúť. Takto totiž bude náš program tým pomalší, čím viac kariet bude maťLacko v kôpke.Lepšie riešenie je použiť na reprezentáciu Lackovej kôpky kariet spájaný

zoznam. Takto vieme zobrať kartu zo začiatku aj pridať kartu na koniec priamo,bez toho, aby nás trápilo, koľko kariet je medzi nimi.

Listing programu:

Page 86: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

84 Riešenia krajského kola kategórie B

program fronta1;type pzaznam = ˆtzaznam;

tzaznam = recordprev, next : pzaznam;hodnota : char;

end;var zaciatok, koniec : pzaznam;

prikaz : longint;karta : string;

procedure pridaj(co : char);var tmp : pzaznam;begin

{ vytvorime a inicializujeme novy zaznam }getmem(tmp,sizeof(tzaznam));tmpˆ.hodnota := co; tmpˆ.next:=nil;

{ ak je fronta prazdna, vytvorime novu, inak ho pridame na koniec }if (zaciatok=nil) then begin

tmpˆ.prev:=nil; zaciatok:=tmp;end else begin

tmpˆ.prev:=koniec; koniecˆ.next:=tmp;end;koniec:=tmp;

end;

function vyber : char;var tmp : pzaznam;begin

{ vratime hodnotu z prveho zaznamu a vymazeme ho z pamate }vyber := zaciatokˆ.hodnota;tmp := zaciatok;zaciatok := zaciatokˆ.next;freemem(tmp);

end;

beginzaciatok := nil; koniec := nil;while true do begin

read(prikaz);case prikaz of

1 : begin readln(karta); pridaj(karta[2]); end;2 : writeln(vyber);0 : halt;

end;end;

end.

Page 87: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia krajského kola kategórie B 85

Rovnako efektívne riešenie, ale jednoduchšie na naprogramovanie dostanemenasledovne: budeme si Lackove karty pamätať ako súvislý úsek prvkov poľa. Keďpríde nová karta, pridáme ju na koniec úseku (ten sa tým natiahne „dopravaÿ),keď máme zahrať kartu, zoberieme ju zo začiatku (tým sa nám úsek skráti).Ak ale zvolíme pole konečnej dĺžky, ako zabezpečiť, aby sme z neho časom

nevybehli? Jednoducho: Vždy, keď takto prídeme úsekom na koniec poľa, za-čneme nové prvky pridávať znova od začiatku. A ešte jeden detail: Aby sa námto celé nepomiešalo, zvolíme si pole väčšej dĺžky ako je celkový počet kariet.

Listing programu:program fronta2;var fronta : array[0..146] of char;

zac, kon : longint; { zac=zaciatok useku, kon=prve volne miesto za nim }prikaz : longint;karta : string;

procedure pridaj(co : char);begin

fronta[kon] := co;kon := (kon+1) mod 147;

end;function vyber : char;begin

vyber := fronta[zac];zac := (zac+1) mod 147;

end;

beginzac:=0; kon:=0;while true do begin

read(prikaz);case prikaz of

1 : begin readln(karta); pridaj(karta[2]); end;2 : writeln(vyber);0 : halt;

end;end;

end.

Obe uvedené riešenia spracujú každú inštrukciu s konštantnou časovou zlo-žitosťou.

Page 88: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

86 Riešenia krajského kola kategórie B

B-II-4 Assembler II

Prvú úlohu vyriešime ľahko. Presunieme obsah Rj do R7. Zmažeme obsahRi. Na záver presunieme obsah R7 naraz aj do Ri, aj do Rj . Musíme si daťpozor na situácie, kedy je v Ri alebo Rj nula.Definujeme teraz pomocnú inštrukciu „add Ri, Rjÿ, ktorá k hodnote v Ri

pridá hodnotu z Rj (a tú nechá nezmenenú). Toto spravíme rovnako ako priinštrukcii mov, len vynecháme dva riadky, ktoré nulujú obsah Ri.Pomocou inštrukcie add teraz definujeme inštrukciumul zo zadania. Presu-

nieme hodnotu Ri do R6. Skopírujeme hodnotu Rj do R5. Teraz hodnotu z R6(hodnota z R5)-krát pripočítame k hodnote (pôvodne teda nule) v Ri. Nakoniecuž len vynulujeme R6.

///// mov R i R j /////a: test Rj , Rj

jz bdec Rj

inc R7jmp a

b: dec Ri

jnz bc: test R7, R7jz kdec R7inc Ri

inc Rj

jmp ck:

///// mul R i R j /////a: test Rj , Rj

jz bdec Rj

inc R6jmp a

b:mov Rj , R5c: test R5, R5jz ddec R5add Ri, R6jmp c

d: dec R6jnz d

Všimnime si ešte, ako dlho trvá vykonanie nami definovaných inštrukcií. Navykonanie mov potrebujeme inštrukcií lineárne veľa od súčtu hodnôt Ri a Rj .Pri add nemusíme nulovať Ri, takže počet inštrukcií je priamo úmerný hodnotev Rj . Pri inštrukcii mul bude počet krokov lineárne závisieť od výsledného sú-činu. (V špeciálnom prípade, kedy je jeden z činiteľov 0, nebude počet inštrukcii0, ale bude úmerný obsahu druhého z násobených registrov. Toto nás ale prinašom využívaní tejto inštrukcie trápiť nebude.)

S počítaním odmocniny to bude trochu zložitejšie. Optimálne riešenie jepomerne jednoduché, ale ukážeme si predtým niekoľko iných, pomalších riešení.

Page 89: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia krajského kola kategórie B 87

Začnime riešením, na ktoré netreba v podstate nič vymýšľať. Postupne bu-deme zväčšovať hodnotu v registri R0. Zakaždým spočítame (pomocou inštruk-cie mul) jej druhú mocninu a tú porovnáme s hodnotou v R1. Akonáhle budevypočítaná druhá mocnina väčšia ako obsah R1, zmenšíme obsah R0 o jedna askončíme.Jediná vec, ktorú ešte nevieme robiť, je „tú porovnáme s hodnotou v R1ÿ.Definujme inštrukciu na porovnanie registrov „jg Ri, Rj , xÿ (jump if grea-

ter), ktorá bude fungovať nasledovne: Porovnaj obsahy Ri a Rj . Oba registrevynuluj. Ak bol obsah Ri väčší, pokračuj skokom na návestie x, inak pokračujďalšou inštrukciou.

///// jg R i R j x /////a: test Ri, Ri

jz zledec Ri

test Rj , Rj

jz dobredec Rj

jmp adobre: dec Ri

jz xjmp dobre

zle: dec Rj

jnz zle

Aké efektívne je toto riešenie? Nech je správna odpoveď k. Potom náš algo-ritmus postupne vypočíta hodnoty 12, 22, . . . , (k+1)2, a každú z nich porovnás k. Na výpočet hodnôt potrebujeme čas úmerný súčtu vypočítaných hodnôt,teda O(k3) krokov. Porovnanie dvoch hodnôt trvá čas úmerný väčšej obochhodnôt. V našom prípade je to skoro vždy obsah registra R1, a ten je približnerovný k2. Porovnaní robíme k, preto pri všetky porovnaniach dokopy spravímeO(k3) krokov.Ak označíme hodnotu v R1 ako n, náš algoritmus potrebuje O(n

√n) krokov.

Funkcia na porovnanie hodnôt sa dá v našom prípade napísať aj šikovnejšie,ak si trochu zmeníme, ako má fungovať. Spolu so zmenšovaním oboch hodnôtbudeme zväčšovať hodnotu v novom pomocnom registri. Keď teraz vynulujemeniektorý z registrov, zapamätáme si (skokom do vhodnej časti programu), ktorý

Page 90: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

88 Riešenia krajského kola kategórie B

register to bol, a spravíme opačný proces. Pomocný register budeme nulovať,pôvodné dva zároveň s tým zväčšovať. Skončíme v situácii, v ktorej sme začínali,iba navyše vieme, ktorý z registrov má väčší obsah. Takto upravené porovná-vanie je lineárne od menšieho z oboch porovnávaných čísel. (Asymptotickúčasovú zložitosť predchádzajúceho riešenia to nezlepší, ale zlepšenie to je.)

Prefíkanejšie riešenie je neskúšať postupne všetky hodnoty k, ale len nie-ktoré. Použijeme niečo podobné binárnemu vyhľadávaniu: postupne skúsimeako k hodnoty 1, 2, 4, 8, 16, . . . , až kým k2 neprekročí obsah R1. V tomto oka-mihu máme v R0 hodnotu 2x a vieme, že správne k je v rozsahu 2x−1 ≤ k < 2x.A teraz už môžeme použiť sľubované binárne vyhľadávanie a na ďalších x − 1„otázokÿ nájsť presnú hodnotu k.(Príklad: Ak sme zistili, že k = 8 ešte nie je veľa a k = 16 už veľa je, budeme

postupne skúšať k = 12, a napr. ďalej k = 14 a k = 13.)Oproti predchádzajúcemu algoritmu sme na tom lepšie: zatiaľ čo ten po-

treboval vyskúšať k hodnôt, tomuto stačí 2 log2 k. Náš nový algoritmus tedaspraví O(k2 log k) krokov. Ak označíme hodnotu v R1 ako n, tento algoritmuspotrebuje O(n logn) krokov.

Stále to ale ide aj lepšie, a prekvapujúco jednoducho. Predstavme si, že vpremennej y máme štvorec premennej x. Ako vypočítať štvorec premennej x+1?Platí (x+1)2 = x2+2x+1. Takže stačí k y pripočítať dvojnásobok x a ešte 1.V našom programe budeme robiť presne to isté, len namiesto pripočítavania

k y budeme rovno odpočítavať od hodnoty v registri R1. Bude teda platiť, žekeď v R0 bude hodnota x, v R1 bude n − x2. A jednoducho povedané, keď sanám R1 minie, skončíme.Časová zložitosť tohoto riešenia je zjavne lineárna od obsahu R1, teda O(n).

Program vyzerá nasledovne:

///// odmocnina /////a: sub R1, R0

sub R1, R0jz koniecdec R1inc R0jmp a // teraz plati: v R 0 je x, v R 1 je n-x^2

koniec:

Page 91: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia krajského kola kategórie B 89

(V programe používame inštrukciu „sub Ri, Rjÿ. Tá vyzerá presne rovnakoako „add Ri, Rjÿ, len namiesto inštrukcie „inc Riÿ je v nej „dec Riÿ. Výsledokje teda taký, že od hodnoty v Ri odčíta hodnotu z Rj .)

Page 92: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia celoštátneho kola kategórie A

A-III-1 Pizza vracia úder

Efektívne riešenia tejto úlohy budú založené na metóde dynamického prog-ramovania. Zaujímať nás budú hodnoty D(s, p) definované nasledovne: D(s, p)je 1 (true, pravda), ak sa dá dosiahnuť výsledná suma s použitím prvých p po-ložiek zo vstupu. Riešením zadanej úlohy je zjavne najmenšie nezáporné s také,že D(s,N) je pravda.Základné riešenie:Nech S je súčet všetkých položiek ai zo vstupu. Zjavne žiadny dosiahnuteľný

výsledok nebude v absolútnej hodnote väčší ako S. Preto sa stačí obmedziť nahodnoty D(s, p), kde s ∈ {−S, . . . , S}.Hodnoty D(s, p) vieme počítať pomocou nasledujúcich vzťahov:

D(s, 0)def= [s = 0]

D(s, p)def= D(s− ap, p− 1) ∨ D(s+ ap, p− 1)

Slovne: Pomocou 0 položiek vieme vyrobiť len sumu 0. Pomocou p položiekvieme sumu s vyrobiť práve vtedy, ak vieme pomocou p − 1 položiek vyrobiťaspoň jednu zo súm s− ap a s+ ap.Takéto riešenie má časovú zložitosť O(SN). Keďže každé ai je najviac K,

vieme, že S ≤ KN , a teda časová zložitosť tohoto algoritmu je O(KN2).V nasledujúcich častiach budeme toto riešenie postupne zlepšovať.Kompresia vstupných údajov:Všimnime si, že výsledok nezáleží na poradí položiek na vstupe, iba na tom,

koľkokrát sa ktoré číslo z intervalu 1 až K vyskytuje v Marcovej postupnosti.Označme ni počet výskytov čísla i. Úlohu si teraz môžeme preformulovať na-sledovne: hľadáme K čísel xi (kde 0 ≤ xi ≤ ni) takých, že pokiaľ xi výskytovčísla i prehlásime za príjem a ni −xi za výdaj, zisk bude nezáporný a najmenšímožný.Veľkosť výsledku:Riešenie úlohy je menšie ako 2K. Ak by totiž mal byť výsledný zisk 2K alebo

ešte viac, môžeme zmeniť niektoré + na -, čím zmenšíme zisk a ešte neklesnemedo záporu.Ako na veľké počty položiek:

Page 93: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia celoštátneho kola kategórie A 91

Predstavme si napríklad situáciu, kedy K = 5 a Marco má na zozname mi-lión položiek s hodnotou 3. Intuícia hovorí, že nič nepokazí, ak zhruba polovicuz nich dá ako prijmy a druhú polovicu ako výdaje.Ak by sme takéto niečo vedeli poriadne sformulovať a dokázať, dosť silne by

to nášmu riešeniu pomohlo.Ako by takéto tvrdenie mohlo vyzerať? Nejako takto: „Nech je nejaké ni

dosť veľké, potom existuje optimálne riešenie, kde nemajú všetky položkyveľkosti i rovnaké znamienka.ÿAk takéto tvrdenie dokážeme, vieme ho nasledovne využiť: „Nech je nejaké

ni dosť veľké. Potom existuje optimálne riešenie, v ktorom je aspoň jedenvýskyt i ako príjem a jeden ako výdaj. Tieto dva výskyty môžeme teda vynechať.To znamená, že ak v pôvodnej úlohe zmenšíme ni o 2, optimálne riešenie sa týmnezmení.ÿZostáva prísť na to, čo máme dosadiť namiesto „dosť veľkéÿ, aby to platilo.

Predstavme si, že už máme nejaké optimálne riešenie. Nech p je veľkosťpoložky, ktorá nás zaujíma. Jediné zaujímavé situácie sú keď xp = 0 alebo xp =np, teda keď majú všetky výskyty položky p rovnaké znamienko. Rozoberiemesituáciu, keď sú všetky kladné, pre záporné to bude vyzerať podobne.Rozdeľme položky na príjmy a výdaje. To, čo teraz chceme dosiahnuť, je

nájsť niekoľko výdajov, ktoré budú mať dokopy súčet p, 2p, . . . , alebo (np−1)p.Ak sa nám toto podarí, môžeme tieto výdaje zmeniť na príjmy a zodpoveda-júci počet príjmov veľkosti p na výdaje. A tým vyhráme, lebo dosiahneme, ženiektoré výskyty položky p budú príjmy a niektoré budú výdaje.Nech P je súčet príjmov. Teraz využijeme, že vieme ohraničiť výsledok:

Keďže výsledok je menší ako 2K, musí byť súčet výdajov V > P − 2K. Keďžekaždý výdaj je najviac K, bude výdajov aspoň ⌈V/K⌉.Z toho dostávame, že ak P ≥ K(p+ 1), bude výdajov aspoň p.

Keď teraz máme aspoň p výdajov, vyberme si z nich presne p a označme ichv1, . . . , vp. Všimneme si teraz tieto súčty: 0, v1, v1+ v2, . . . , v1+ · · ·+ vp. Totoje p + 1 rôznych čísel. Podľa Dirichletovho princípu niektoré dve z nich musiadávať po delení p rovnaký zvyšok. Nech sú to súčty po vi a po vj .Potom číslo vi+1 + · · ·+ vj je násobkom p. Presnejšie, je to číslo z množiny

{p, 2p, . . . , Kp}.

Platí teda tvrdenie: „Nech pre nejaké p platí np > 2K. Potom optimálneriešenie je rovnaké ako keby np bolo o 2 menšie.ÿ

Page 94: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

92 Riešenia celoštátneho kola kategórie A

Dôkaz: Zoberme ľubovoľné optimálne riešenie. Ako sme už povedali, jedinédva zlé prípady sú, ak v ňom berieme všetky položky p ako príjmy / všetky akovýdaje.V prvom prípade ale vieme, že P ≥ npp ≥ (2K + 1)p = Kp + (Kp + p) >

Kp+K, a teda bude aspoň p výdajov. Potom ale vieme nájsť niekoľko výdajov,ktorých súčet je násobkom p a je menší ako npp. Tieto výdaje zmeníme napríjmy a niekoľko príjmov veľkosti p na výdaje.Druhý prípad vyzerá analogicky. Ak by všetky pi boli výdaje, príjmov musí

byť aspoň toľko ako v prvom prípade výdajov. Preto tentokrát medzi príjmamivyberieme vhodnú množinu, ktorú vymeníme s výdajmi veľkosti p.Prvý lepší algoritmus:Pozrieme sa na hodnoty ni a každú z nich upravíme, aby bola nanajvýš

rovná 2K. (Ak teda nejaké ni bolo viac ako 2K, po úprave bude buď 2K, alebo2K − 1, podľa jeho parity.)Teraz zoberieme takto zmenšenú množinu príjmov a výdajov a pre ne pou-

žijeme pôvodný algoritmus s časovou zložitosťou O(NS).Teraz už ale vieme povedať, že (upravený) počet všetkých položiek je N =

O(K2) a súčet všetkých položiek je S = O(K3), a teda náš algoritmus máčasovú zložitosť O(K5). Presnejšie O(N + K5), lebo v O(N) musíme načítaťvstup.Veľkosť priebežných výsledkov:Zatiaľ sme sa nijako nezaoberali tým, či nám naozaj treba uvažovať všetky

možné priebežné súčty, ktoré sa dajú dosiahnuť. Podobne ako pri obmedzenípočtov položiek budeme chcieť ukázať, že (bez ohľadu na usporiadanie položiek)existuje optimálne riešenie, v ktorom žiaden priebežný zisk nie je (v absolútnejhodnote) príliš veľký.

Základná myšlienka bude podobná ako pri zmenšovaní počtov položiek:Predstavme si, že máme optimálne riešenie, pri ktorom je nejaký medzisúčet

M veľmi veľký. Ako by sa dalo takéto riešenie upraviť na iné, rovnako dobré,pri ktorom bude tento medzisúčet menší?KeďžeM je veľké, znamená to, že z položiek, ktoré dávajú tento medzisúčet,

sme veľa prehlásili za príjmy. A naopak, keďže vieme, že výsledok je malý, budemedzi zvyšnými položkami veľa takých, ktoré sme prehlásili za výdaje.Ak by sme teraz vybrali niekoľko zo spominaných príjmov a niekoľko zo

spomínaných výdajov tak, aby dali dokopy súčet nula, vieme medzisúčet Mzmenšiť tak, že zmeníme znamienko všetkým nájdeným príjmom a výdajom.

Page 95: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia celoštátneho kola kategórie A 93

Ešte raz a poriadne. Dokážeme, že platí nasledovné tvrdenie: „Existuje opti-málne riešenie, v ktorom je absolútna hodnota každého čiastočného súčtu men-šia ako 2K2 + 3K.ÿAby sme toto dokázali, ukážeme, že ak máme väčší čiastočný súčet, vieme ho

zmenšiť, a pritom nezväčšiť žiaden iný čiastočný súčet a nepokaziť optimálnosťriešenia. (Pre záporné čiastočné súčty dôkaz neuvádzame, vyzerá analogicky.)Majme teda optimálne riešenie, v ktorom súčet prvých x položiek je M ≥

2K2 + 3K. Teraz pôjdeme od x-tej položky k prvej a budeme vyberať položky,ktoré sú v našom optimálnom riešení príjmami. Prestaneme, keď súčet vybra-ných položiek prekročí K2.Ďalej pôjdeme od (x + 1)-ej položky k N -tej a budeme vyberať tie, ktoré

sú v našom riešení výdaje. Prestaneme tesne pred tým, ako by súčet všetkýchvybraných položiek klesol pod nulu.Zjavne takto vyberieme aspoň K príjmov a aspoň K výdajov.Všimnime si, že všetky čiastočné súčty, ktoré zodpovedajú úseku, z ktorého

sme práve vybrali príjmy, sú väčšie alebo rovné K2 + 2K. A teda ak by sme ajvšetkých K vybratých položiek zmenili z príjmov na výdaje, budú všetky tietočiastočné súčty naďalej kladné, a teda sa ich absolútne hodnoty zmenšia.Teraz potrebujeme ukázať, že existuje nejaká neprázdna podmnožina nami

vybraných príjmov a výdajov, ktorá má súčet 0.To spravíme nasledovne: Usporiadajme vybrané príjmy a výdaje do postup-

nosti p1, p2, . . . tak, aby všetky čiastočné súčty p1 + · · · + pq boli z množiny{0, . . . , 2K − 1}. (Rozmyslite si, že toto vieme vždy spraviť.) Keďže má našapostupnosť aspoň 2K členov, a teda aspoň 2K+1 čiastočných súčtov, musia byťdva čiastočné súčty rovnaké, a teda má zodpovedajúci úsek postupnosti súčetnula.Ak teraz zoberieme zodpovedajúce príjmy a výdaje v optimálnom riešení a

zmeníme im znamienka, dostaneme nové optimálne riešenie, pričom sme zmen-šili niektoré čiastočné súčty (vrátane toho vybraného veľkého) a ostatné čias-točné súčty zostali nezmenené.Tento proces môžeme opakovať, až kým nedostaneme optimálne riešenie,

kde sú všetky čiastočné súčty malé. Analogicky sa vieme zbaviť príliš zápornýchčiastočných súčtov.Druhý lepší algoritmus:Vieme už, že stačí hľadať také riešenia, v ktorých sú všetky čiastočné súčty

medzi −2K2 − 3K a 2K2 + 3K. Keď pridáme toto ohraničenie do predchádza-júceho riešenia, dostávame algoritmus s časovou zložitosťou O(N +K4).

Page 96: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

94 Riešenia celoštátneho kola kategórie A

Šikovnejšie počítanie dosiahnuteľných medzisúčtov:Položky s rovnakou hodnotou budeme spracúvať všetky naraz.Teraz nás teda budú zaujímať nové hodnoty E(s, p) definované nasledovne:

E(s, p) je 1 (true, pravda), ak sa dá dosiahnuť výsledná suma s použitím všet-kých položiek, ktoré majú hodnoty 1 až p. Riešením zadanej úlohy je zjavnenajmenšie nezáporné s také, že E(s,K) je pravda.

Pre p > 0 platí: E(s, p) je pravda práve vtedy, ak je pravda aspoň jedna zhodnôt E(s− pnp, p− 1), E(s− p(np − 2), p− 1), . . . , E(s+ pnp, p− 1).Slovne: pomocou položiek s veľkosťami 1 až p vieme sumu s vyrobiť vtedy

a len vtedy, ak vieme pomocou položiek menších ako p vyrobiť nejakú sumu s′

takú, že s− s′ vieme vyrobiť pomocou položiek veľkosti p.Ak by sme hodnoty E(s, p) počítali priamo podľa tejto definície, dostali by

sme rovnako efektívne riešenie ako v predchádzajúcom prípade.Na to, aby sme dosiahli lepšiu časovú zložitosť, všimnime si nasledujúcu

vec: Ak nás zaujíma, či platí E(s+ 2p, p), budeme sa pozerať na skoro tie istéhodnoty E(?, p− 1) ako keď sme zisťovali, či platí E(s, p).

Ako si túto prácu ušetriť? OznačmeM(s, p) = E(s− pnp, p− 1) +E(s− p(np − 2), p− 1) + · · ·+E(s+ pnp, p− 1).Slovne,M(s, p) je počet takých súm, ktoré sa dajú naskladať z položiek menšíchako p, a z ktorých vieme položkami veľkosti p vyrobiť sumu s.

M(s, p) je takmer to isté ako E(s, p), len namiesto ∨ sme použili +. Zjavneteda E(s, p) je pravda práve vtedy, keď M(s, p) je kladné.Čo sme tým získali? To, že vieme, že platí nasledujúci vzťah:

M(s+ 2p, p) =M(s, p)− E(s− pnp, p− 1) +E(s+ 2p+ pnp, p− 1)Takže „hrubou silouÿ stačí spočítať prvých 2p hodnôt M(?, p), každú ďalšiu

dostaneme v konštantnom čase.

Na výpočet jednej hodnoty hrubou silou potrebujeme čas O(np), čo viemezhora odhadnúť ako O(K). Výpočet 2p hodnôt hrubou silou teda bude trvaťO(K2). Ostatných hodnôt, ktoré budeme počítať, je O(K2).Celkovo teda vieme pre konkrétne p spočítať všetky hodnoty E(?, p) v čase

O(K2). Tým dostávame algoritmus s časovou zložitosťou O(N +K3).

Listing programu:program zisk;const MAXK = 100; { maximalnı velikost prıjmu ci vydaje }

MAXZ = 2 * MAXK * (MAXK + 2); { maximalnı velikost prvku Z_t }

Page 97: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia celoštátneho kola kategórie A 95

type mnozina = record { true je nastaveno na pozicıch vsech prvku mnoziny }prvky : array[-MAXZ .. MAXZ] of boolean;

end;var m : array[1 .. 2] of mnozina; { mnoziny Z_t a Z_(t+1) }

predchozi : integer; { Z_t je m[predchozi], Z_(t+1) je m[3-predchozi] }k : integer;amaxz : integer; { 2k(k+2) }ni : array[1 .. MAXK] of integer; { cisla n_i }mz : array[-MAXZ .. MAXZ] of integer; { cısla m_z ... }

{ ve skutecnosti by stacilo si pamatovat jen poslednıch 2t }

{ Inicializuje MN na prazdnou mnozinu }procedure smaz (var mn : mnozina);var i : integer;begin for i := -amaxz to amaxz do mn.prvky[i] := false; end;

{ Vratı true pokud X je prvkem mnoziny MN }function je_prvek (var mn : mnozina; x : integer) : boolean;begin je_prvek := (abs (x) <= amaxz) and mn.prvky[x]; end;

{ Z mnoziny Z_(T-1) (P) vytvorı mnozinu Z_T (MN) }procedure dalsi_zisky (var p, mn : mnozina; t : integer);var yt, i, z, max_yt : integer;beginmax_yt := t * ni[t];{ spocteme cısla m_z pro z v rozmezı -amaxz ... -amaxz + 2t-1 }for z := -amaxz to -amaxz + 2 * t - 1 do begin

i := 0;yt := -max_yt;while yt <= max_yt do begin

if je_prvek (p, z + yt) then inc (i);inc (yt, 2 * t);

end;mz[z] := i;

end;{ a nynı zbyvajıcı hodnoty m_z }for z := -amaxz + 2 * t to amaxz do begin

i := mz[z - 2 * t];if je_prvek (p, z + max_yt) then inc (i);if je_prvek (p, z - 2 * t - max_yt) then dec (i);mz[z] := i;

end;{ do mnoziny mn dame cısla z takova, ze m_z nenı nula }for z := -amaxz to amaxz do if mz[z] <> 0 then mn.prvky[z] := true;

end;

{ Vratı nejmensı nezaporne cıslo v mnozine MN }function minimum (var mn : mnozina) : integer;var i : integer;begin

Page 98: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

96 Riešenia celoštátneho kola kategórie A

for i := 0 to amaxz doif mn.prvky[i] then begin minimum := i; break; end;

end;

{ Nacte seznam prıjmu ci vydaju }procedure nacti;var i, n, a : integer;beginreadln (n, k);amaxz := 2 * k * (k + 2);for i := 1 to k do ni[i] := 0;for i := 1 to n do begin read (a); inc (ni[a]); end;

end;

{ Omezı cısla n_i na nanejvys 2k+1 }procedure omez_ni;var i : integer;beginfor i := 1 to k do

if ni[i] > 2 * k + 1 then beginif odd(ni[i]) then ni[i] := 2 * k + 1 else ni[i] := 2 * k;

end;end;

var t : integer;beginnacti;omez_ni;smaz (m[1]); smaz (m[2]);predchozi := 1;{ Z_0 = (0) }m[predchozi].prvky[0] := true;for t := 1 to k do begin

dalsi_zisky (m[predchozi], m[3 - predchozi], t);smaz (m[predchozi]);predchozi := 3 - predchozi;

end;writeln (minimum (m[predchozi]));

end.

A-III-2 Obdĺžnik

Ukážeme si riešenie, ktorého časová zložitosť je O(N2) a jeho pamäťovénároky sú lineárne od počtu daných bodov.Najprv vymyslíme, ako pre daný obdĺžnik A1A2A3A4 rýchlo určiť počet

bodov, ktoré ležia vnútri tohto obdĺžnika. Pre každý bod Bi spočítame početbodov Bi′ , ktorých x-ová súradnica je väčšia alebo rovná x-ovej súradnici bodu

Page 99: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia celoštátneho kola kategórie A 97

Bi a zároveň y-ová súradnica je ostro menšia než y-ová súradnica bodu Bi.Tento počet označíme a1i . Podobne, a

2i bude počet bodov s x-ovou súradnicou

ostro väčšou a y-ovou súradnicou väčšou alebo rovnou, a3i počet bodov s x-ovou súradnicou menšou alebo rovnou a y-ovou ostro väčšou a konečne a4i budepočet bodov s x-ovou ostro menšou a y-ovou menšou alebo rovnou. Každé zčísel a1i , a

2i , a

3i a a

4i je ľahké vypočítat v čase O(N) (pre jeden bod Bi). Teda

na spočítanie všetkých 4N čísel a1i , a2i , a

3i a a4i , 1 ≤ i ≤ n, spotrebujeme čas

O(N2).Ľahko nahliadneme, že pokiaľ vrchol Aj obdĺžnika A1A2A3A4 je bod Bij ,

potom počet bodov ležiacich vnútri obdĺžnika A1A2A3A4 je N − a1i1 − a2i2 −a3i3−a4i4 (viď obrázok). Pre jeden obdĺžnik A1A2A3A4 môžeme teda určiť početbodov, ktoré ležia vnútri tohto obdĺžnika, v konštantnom čase.

Bi1 Bi2

Bi3Bi4

a1i1

a2i2

a3i3

a4i4

(Poznámka: Existujú aj iné možné postupy, napr. pre vhodné body si spo-čítame počet bodov, ktoré ležia v ľavom hornom kvadrante od daného bodu, az týchto informácií poskladáme v konštantnom čase počet bodov v ľubovoľnomobdĺžniku. Väčšina alternatívnych postupov ale potrebuje pamäť O(N2).)

Teraz si popíšeme, ako môžeme rýchlo najsť všetky obdĺžniky A1A2A3A4,ktorých hrany sú rovnoběžné s osami a ktorých vrcholy sú v niektorých zozadaných bodov. Najprv si všetky body zotrieďme vzostupne podľa x-ovej sú-radnice a tie body, ktoré majú zhodnú x-ovú súradnicu, zotriedime medzi sebouvzostupne podľa y-ovej súradnice. Pre každý bod Bi teraz môžeme vypísať tiebody, ktoré majú rovnakú x-ovú súradnicu ako Bi a väčšiu y-ovú súradnicu,v čase lineárnom od ich počtu. Podobne si zotriedime všetky body podľa y-ovejsúradnice a v prípade zhody podľa x-ovej, aby sme mohli ľahko nájsť body s rov-nakou y-ovou a väčšou x-ovou súradnicou. Na zotriedenie bodov potrebujemečas O(N logN) (použijeme napr. triediaci algoritmus heapsort alebo quicksort)

Page 100: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

98 Riešenia celoštátneho kola kategórie A

a na uloženie zotriedeného zoznamu bodov vrátane odkazov doňho potrebujemepamäť lineárnu od N .Teraz si popíšeme postup, ako nájsť všetky obdĺžniky A1A2A3A4, ktoré

spĺňajú podmienky zo zadania úlohy. Zafixujeme jeden bod Bi a určíme všetkybody Bj také, že bod Bi je vrchol A1 a bod Bj vrchol A3 nejakého obdĺžnikuA1A2A3A4 (všimnite si, že vrcholy A2 a A4 sú bodmi Bi a Bj jednoznačneurčené).K nájdeniu všetkých takýchto bodov Bj pre bod Bi si vytvoríme pomocné

pole C, ktorého všetky zložky C[j] budú na začiatku rovné nule. Potom vezmemevšetky body Bi′ , ktoré majú rovnakú x-ovú súradnicu ako Bi a zároveň väčšiuy-ovú súradnicu, a pre každý takýto bod Bi′ vezmeme všetky body Bi′′ , ktorémajú rovnakú y-ovú a väčšiu x-ovú súradnicu než Bi′ . Body Bi′ zvládneme najsťv lineárnom čase od ich počtu a rovnako body Bi′′ pre každý bod Bi′ viemenajsť v lineárnom čase od ich počtu. Pretože body Bi′′ sú rôzne pre rôzne bodyBi′ , trvá nájdenie všetkých bodov Bi′′ čas lineárny od N . Zložku C[i′′] poľa Czvýšime o jedna pre každý bod Bi′′ , ktorý sme takto našli. Zdôrazňujeme, žeteraz je každá zložka poľa C rovná buď 0 alebo 1.Potom pre bod Bi vezmeme všetky body Bi′ s rovnakou y-ovou a väčšou

x-ovou súradnicou a pre také body Bi′ nájdeme všetky body Bi′′ s rovnakoux-ovou súradnicou a väčšou y-ovou súradnicou. Za každý takýto bod zvýšimehodnotu C[i′′] o jedna. Zložky poľa C sú teraz rovné 0, 1 alebo 2. Ďalej platí, žeC[j] je rovné 2 vtedy a len vtedy, keď pre body Bi a Bj existuje bod, ktorý márovnakú x-ovú súradnicu ako Bi a rovnakú y-ovú súradnicu ako Bj , a zároveňexistuje bod, ktorý má rovnakú x-ovú súradnicu ako Bj a rovnakú y-ovou sú-radnicu ako Bi. Potom ale takéto dva body tvoria vrcholy A2 a A4 obdĺžnika,ktorého vrchol A1 je Bi a vrchol A3 je Bj . Pre daný bod Bi môžeme teda v časeO(N) nájsť všetky body Bj , ktoré tvoria protiľahlé vrcholy A1 a A3 nejakéhoobdĺžnika A1A2A3A4. Určiť počet vnútorných bodov takéhoto obdĺžnika viemev konštantnom čase, ako sme si vysvetlili na začiatku riešenia.Ako sme si práve popísali, dá sa pre daný bod Bi v čase O(N) nájsť všetky

obdĺžniky s ľavým dolným rohom Bi, a pre každý z nich spočítať, koľko bodovv ňom leží. Toto spravíme pre každé i.Výsledný algoritmus má časovú zložitosť O(N2) a pamäťovú O(N).

Listing programu:program obdelniky;const MAXN=1000; { maximalnı pocet zadanych bodu }var N,i: longint;

sorted_by_x, sorted_by_y, index_by_x, index_by_y: array[1..MAXN] of longint;

Page 101: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia celoštátneho kola kategórie A 99

Bx, By, A1, A2, A3, A4, C: array[1..MAXN] of longint;nejlepsi_pocet: longint;

procedure spocitej_A;var i,j: longint;beginfor i:=1 to N do begin

A1[i]:=0; A2[i]:=0; A3[i]:=0; A4[i]:=0;for j:=1 to N do begin

if (Bx[j]>=Bx[i]) and (By[j]<By[i]) then inc(A1[i]);if (Bx[j]>Bx[i]) and (By[j]>=By[i]) then inc(A2[i]);if (Bx[j]<=Bx[i]) and (By[j]>By[i]) then inc(A3[i]);if (Bx[j]<Bx[i]) and (By[j]<=By[i]) then inc(A4[i]);

end;end;

end;

{ funkcie quick_?, ktore pouzitim quicksortu utriedia pole sorted_by_?podla ?-ovej suradnice, z priestorovych dovodov neuvadzame }

procedure setrid;var i:longint;beginfor i:=1 to N do begin sorted_by_x[i]:=i; sorted_by_y[i]:=i; end;quick_x(1,N); for i:=1 to N do index_by_x[sorted_by_x[i]]:=i;quick_y(1,N); for i:=1 to N do index_by_y[sorted_by_y[i]]:=i;

end;

procedure zkus_vrchol(i: longint);var i1, i2, j: longint;

a2_index, a4_index: array[1..MAXN] of longint;beginfor j:=1 to N do C[j]:=0;i1:=index_by_x[i]+1;while Bx[sorted_by_x[i1]]=Bx[i] do begin

i2:=index_by_y[sorted_by_x[i1]]+1;while By[sorted_by_y[i2]]=By[sorted_by_x[i1]] do begin

inc(C[sorted_by_y[i2]]);inc(i2);a2_index[i2]:=sorted_by_x[i1];

end;inc(i1)

end;i1:=index_by_y[i]+1;while By[sorted_by_y[i1]]=By[i] do begin

i2:=index_by_x[sorted_by_y[i1]]+1;while Bx[sorted_by_x[i2]]=Bx[sorted_by_y[i1]] do begin

inc(C[sorted_by_x[i2]]);inc(i2);a4_index[i2]:=sorted_by_y[i1];

Page 102: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

100 Riešenia celoštátneho kola kategórie A

end;inc(i1)

end;for j:=1 to N do

if (C[j]=2)and (N-A1[i]-A2[a2_index[j]]-A3[j]-A4[a4_index[j]] > nejlepsi_pocet)

then beginnejlepsi_pocet := N - A1[i] - A2[a2_index[j]] - A3[j] - A4[a4_index[j]];

end;end;

beginreadln(N); for i:=1 to N do readln(Bx[i],By[i]); end;spocitej_A;setrid;nejlepsi_pocet:=0;for i:=1 to N do zkus_vrchol(i);if nejlepsi_pocet=0 then writeln(’Nema resenı.’) else writeln(nejlepsi_pocet);

end.

A-III-3 Grafomat a šamani

Na úvod si uvedomme, že stačí vedieť zadanú úlohu riešiť pre stromy. Aktotiž máme našu úlohu riešiť pre 3-graf, môžeme ho z vrcholu, ktorý je nazačiatku označený, prehľadať do šírky. Podobne ako v riešení úlohy z domácehokola si navyše v každom vrchole zapamätáme, odkiaľ sme doň prvýkrát prišli.Takto dostaneme zakorenený strom s koreňom vo vrchole, ktorý bol na začiatkuoznačený.Jednoduchšie ale pomalšie riešenie:Chceme rozdeliť vrcholy stromu na dve rovnako veľké množiny. Keby sme

túto úlohu riešili na klasickom počítači, mohli by sme vymyslieť napríkladnasledujúce riešenie: prehľadáme celý strom do hĺbky a vrcholy v poradí, vakom ich objavujeme, farbíme striedavo na červeno a na modro. V Pascale byto vyzeralo napríklad nejako takto:function prejdi_strom ( v:vrchol ; f:farba ) : farba;var i : integer;begin

if (f=cervena) f:=modra else f:=cervena;v.farba := f;for i:=1 to v.pocetSynov do f := prejdi_strom( v.syn[i], f );

end;

Toto riešenie vieme naprogramovať aj v grafomate. Namiesto rekurzie sibudeme medzi vrcholmi odovzdávať značku, ktorá bude reprezentovať miesto,kde sa práve prehľadávanie nachádza. Po každom takte bude v grafe práve jedna

Page 103: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia celoštátneho kola kategórie A 101

značka. Vo vrchole, ktorý má značku, si navyše budeme pamätať naposledypoužitú farbu a to, či sme do vrcholu práve prišli, alebo už chceme odísť z jehopodstromu.Presnejšie to bude prebiehať takto:

1. Na začiatku dostane značku koreň, pamätáme si v ňom, že sme práve prišlia posledná použitá farba bola 0.

2. Ak vrchol má značku a práve sme doň prišli, v nasledujúcom takte zmenípamätanú farbu na opačnú a ofarbí sa ňou. Potom:

• Ak nemá žiadnych synov, značku si nechá a zapamätá si, že chcemeodísť preč.

• Ak má nejakých synov, pošle značku prvému z nich.3. Ak vrchol má značku a pamätáme si, že chceme z neho odísť:

• Ak má mladšieho brata (teda vrchol, ktorý má rovnakého otca a uotca o jedno väčšie poradové číslo), pošle jemu značku a u brata sizapamätáme, že sme práve prišli.

• Ak mladšieho brata nemá, odovzdá značku späť otcovi a zapamätámesi u otca, že budeme z neho chcieť odísť.

• Ak už nemá ani otca, sme v koreni, celý graf je ofarbený a končíme.Tieto pravidlá vieme priamočiaro prepísať do programu pre grafomat. Bude

to fungovať tak trochu naopak. Napríklad namiesto toho, aby sme raz poslaliznačku mladšiemu bratovi, bude sa každý vrchol v každom takte pozerať nasvojho staršieho brata, či ten nemá značku, ktorú chce poslať preč. Keď niekedyvrchol uvidí, že ju jeho starší brat má, nastaví si, že teraz je značka u neho.Toto riešenie má časovú zložitosť úmernú počtu vrcholov v grafe.Ide to však aj lepšie. Vzorové riešenie bude mať časovú zložitosť úmernú

tomu, ako ďaleko je najvzdialenejší vrchol od toho, kde výpočet začíname –teda od hĺbky stromu.Zložitejšie ale rýchlejšie riešenie:Podobne ako v predchádzajúcom riešení začneme tým, že zadaný 3-graf pre-

hľadáme do šírky, čím dostaneme zakorenený strom. Aby bolo naše riešenierýchle, budeme chcieť jeho podstromy ofarbovať paralelne. Čo na to ale potre-bujeme vedieť?Ukážeme si najskôr na príklade približnú myšlienku riešenia, potom dopl-

níme implementačné detaily.Predstavme si, že máme napríklad vrchol v, ktorý má troch synov: a, b a c.

Pozrime sa teraz na podstromy s koreňmi a, b, c. V niektorých z nich je párny

Page 104: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

102 Riešenia celoštátneho kola kategórie A

počet vrcholov. Tieto nás netrápia, lebo sa ich dá ofarbiť presne. Trápiť násbudú tie, kde je počet vrcholov nepárny. Keď ofarbíme taký podstrom „približnesprávneÿ, bude v ňom vrcholov jednej farby o jedno viac ako druhej.Keby sme vo vrchole v vedeli, ktoré z podstromov s koreňmi a, b, c majú

párnu a ktoré nepárnu veľkosť, ľahko by sme všetko vyriešili: do párnych pod-stromov oznámime „ofarbite sa rovnomerneÿ, do približne polovice nepárnychpodstromov oznámime „ofarbite sa tak, aby bolo o jedno viac červenýchÿ a dozvyšku „ofarbite sa tak, aby bolo o jedno viac modrýchÿ.Teraz už k tým sľúbeným detailom. Podrobnejšie bude náš algoritmus vyze-

rať nasledovne:

1. Prehľadáme graf zo začiatočného vrcholu, čím vznikne strom.

2. Budeme si posielať informácie od listov do koreňa a pre každý vrchol sispočítame, či má jeho podstrom párnu alebo nepárnu veľkosť.

3. Keď sa už koreň dozvie svoju paritu (tá určite vyjde párna), začneme pohladinách ofarbovať. V prvom takte tejto časti ofarbíme koreň farbou 0.

4. Ak už je nejaký vrchol v ofarbený, postupne sa ofarbia jeho synovia. Prvýsyn dostane opačnú farbu ako v. Farba každého ďalšieho syna závisí odfarby predchádzajúceho a parity veľkosti jeho podstromu.

(Presnejšie, ak bol predchádzajúci podstrom párnej veľkosti, dostane ďalšísyn rovnakú farbu, inak dostane opačnú.)

Uvedomte si, že ofarbenie, ktoré tento algoritmus vyrobí, bude úplne rovnakéako to, ktoré vyrobil pomalší algoritmus. Iba sme na zrýchlenie použili to, žekeď vieme paritu počtu vrcholov v podstrome, nemusíme čakať na to, ktoráfarba v ňom bude použitá ako posledná – vieme si to vypočítať a rovno začaťfarbiť aj susedný podstrom.Keďže pôvodný graf je 3-graf, nemá žiaden vrchol v strome viac ako troch

synov. (Presnejšie, každý vrchol okrem koreňa má najviac dvoch synov.) Pretokaždú vrstvu stromu ofarbíme na najviac tri takty.

Listing programu:var x: 0..1; { 1=pocatecnı vrchol, 0=ostatnı }

y: 0..2 = 2; { vystupnı barva: 0=cervena, 1=zelena, 2=neurcena }z: 0..4 = 0; { hrana vedoucı k otci vrcholu, 0=neurcena, 4=koren }q: 0..2 = 2; { parita podstromu: 0=suda, 1=licha, 2=neurcena }i, k, l: 0..3 = 0; { pomocne promenne }

beginif z=0 then begin { 1. faze: prohledavanı do sırky (stavenı stromu) }

Page 105: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia celoštátneho kola kategórie A 103

if x=1 then z := 4 { Koren oznacıme specialne }else for i:=1 to 3 do { Kdyz mame oznaceneho souseda, mame otce }

if (S[i].z > 0) or (S[i].x = 1) then z := i;endelse if q=2 then begin { 2. faze: pocıtanı parity }

l := 0; { kolik synu ma lichou paritu }k := 0; { uz muzeme paritu urcit? }for i:=1 to 3 do

if S[i].z = 0 then k := 1 { neprohledany soused => urcit nemuzeme }else if S[i].z = P[i] then { je to syn }

if S[i].q = 2 then k := 1 { syn nema paritu => ani my }else if S[i].q = 1 then l := l+1; { lichy syn }

if k = 0 then q := 1 - l mod 2; { toto funguje i kdyz ma vrchol 0 synu }endelse if y=2 then begin { 3. faze: barvenı }

if (x=1) and (q<2) then y := 0 { dopocıtame paritu => obarvıme koren }else if (z>0) and (S[z].y < 2) then begin { otec uz je obarven => }

y := 1 - S[z].y; { => dopocıtame svou barvu podle parity bratru }k := P[z]; { cıslo hrany vedoucı z otce sem }for i := 1 to k-1 do { za kazdeho licheho starsıho bratra ... }

if S[z].S[i].q = 1 then y := 1 - y; { ... barvu otocıme }end;

end;end.

A-III-4 Polícia zasahuje

Na začiatku si všimnime, že mapa kanalizácie predstavuje strom (čiže súvislýgraf bez kružníc). Označme tento strom T . Môžeme si zvoliť ľubovoľný vrcholu a v ňom tento strom zakoreniť – odteraz bude pre nás u koreňom danéhostromu T . Môžete si to predstaviť tak, že strom chytíme za vrchol u a zavesímeho zaň na stenu.V ďalšom texte budeme označovať Tv podstrom s koreňom v. To je tá časť

stromu, ktorá by odpadla, keby sme vrchol v odstránili.Vrchol v budeme nazývať bezpečný, ak sa žiaden mafián, ktorý býva v pod-

strome Tv, nevie dostať nestráženou cestou do vrcholu v.Náš algoritmus bude postupovať smerom od listov stromu T k jeho koreňu

u. Keď budeme spracúvať nejaký vrchol v, budeme pre neho chcieť spočítať dveveci:

• Aký je minimálny počet strážcov S(v) potrebný na pokrytie podstromuTv tak, aby sa žiadni dvaja mafiáni z neho nemohli stretnúť,

Page 106: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

104 Riešenia celoštátneho kola kategórie A

• a tiež, či vieme týmto počtom strážcov navyše dosiahnuť, aby bol vrcholv bezpečný.

Pre listy je situácia jednoduchá: V liste sa môže nachádzať najviac jedenmafián, a teda nie je potrebné ho oddeľovať. Počet potrebných strážcov je teda0. Tento vrchol je bezpečný práve vtedy, ak v ňom nie je mafián.Nech teraz náš algoritmus ide spracovať vrchol v. Označme si jeho priamych

potomkov v1, . . . , vk. Pre každý z podstromov Tv1 , . . . , Tvkmáme už spočí-

taný minimálny potrebný počet strážcov a aj to, či je pri ich použití vrchol vibezpečný.Označme S = S(v1)+ · · ·+S(vk). Optimálne riešenie pre Tv je určite väčšie

alebo rovné ako S (teda súčet optimálnych riešení pre jednotlivé podstromy),lebo v každom z týchto podstromov musíme od seba oddeliť všetkých mafiánov.My ale navyše musíme oddeliť od seba aj mafiánov v rôznych podstromoch, amožno ešte aj mafiána vo vrchole v. Ukážeme si, ako na to. Rozoberieme dvaprípady.

Vo vrchole v je mafián. Ak majú všetky podstromy bezpečné optimálne rie-šenie, stačí nám na celý strom Tv použiť S strážcov. Lepšie to zjavne nejde.Výsledné rozmiestnenie strážcov určite nebude bezpečné, lebo mafián bý-vajúci vo v sa do v dostať vie.

V opačnom prípade musíme od seba oddeliť mafiána vo vrchole v a ma-fiánov v nebezpečných podstromoch. Musíme teda pridať aspoň jednéhostrážcu. Zjavne stačí pridať práve jedného strážcu, a to do vrcholu v.Takto teda dostaneme riešenie s S + 1 strážcami. Toto riešenie je určitebezpečné.

Vo vrchole v nie je mafián. Ak je najviac jeden podstrom, ktorý nemá bez-pečné optimálne riešenie, stačí nám na celý strom Tv použiť S strážcov.Lepšie to zjavne nejde. Ak boli všetky podstromy bezpečné, bude bez-pečné aj celkové rozmiestnenie, inak nie. (Ten istý mafián, ktorý to kazilv nebezpečnom podstrome, to kazí naďalej.)

V opačnom prípade musíme od seba oddeliť (aspoň dvoch) mafiánov vnebezpečných podstromoch. Musíme teda pridať aspoň jedného strážcu.Zjavne stačí pridať práve jedného strážcu, a to do vrcholu v. Takto tedadostaneme riešenie s S + 1 strážcami. Toto riešenie je určite bezpečné.

Keď takto nakoniec spracujeme vrchol, ktorý sme si zvolili ako koreň stromu,dostaneme optimálny počet strážcov. Ten vypíšeme na výstup a sme hotoví.

Page 107: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia celoštátneho kola kategórie A 105

Spracovať jeden konkrétny vrchol vieme v čase priamo úmernom počtu jehopodstromov, čiže počtu hrán, ktoré z neho vychádzajú. Celkovo má teda tentoalgoritmus časovú zložitosť priamo úmernú súčtu stupňov vrcholov. Ale súčetstupňov vrcholov nie je nič iné ako dvojnásobok počtu hrán. (Každá hrana jezarátaná v dvoch stupňoch vrcholov.)No a keďže zadaný graf je strom a má N − 1 hrán, je časová zložitosť tohto

algoritmu O(N).Iné riešenie:Táto úloha má aj iné lineárne riešenia, sú však náročnejšie na implementáciu

ako vzorové riešenie. Uvedieme myšlienku jedného z nich.Ak máme list stromu, v ktorom nebýva mafián, môžeme tento list a hranu,

ktorá doň vedie, zahodiť, hodnotu optimálneho riešenia to nezmení. Podobneak máme vrchol, z ktorého vedú dve hrany a v ktorom nebýva mafián, môžemeho z grafu odstrániť a jeho dvoch susedov spojiť priamou hranou.Ak už sa v nejakom okamihu žiadna z týchto operácií nedá spraviť, musí

existovať vrchol, ktorého najviac jeden sused nie je list. (Dôkaz a návod nahľadanie: Ak by sme si strom zakorenili, stačí zobrať otca niektorého najhlbšieholistu.)Rozmyslite si, že do tohto vrcholu potom musíme umiestniť strážnika. Tým

sme sa ale zbavili tohto vrcholu a všetkých listov, ktoré s ním susedia. Vyhodímeich z grafu a pokračujeme vyššie popísaným postupom ďalej, až kým už nie ječo riešiť.

Listing programu:#include <stdio.h>#include <stdlib.h>#include <string.h>

#define MAXN 100000

FILE *in, *out; /* Vstupnı a vystupnı soubor */int n, p; /* Pocet vetvenı a pocet mafianu */int deg[MAXN]; /* Pocet stok vedoucıch z vetvenı */int e[MAXN][2]; /* Seznam stok */int edge_ptr[MAXN]; /* Index v neib, kde zacınajı sousede kazdeho vetvenı */int neib[2*MAXN]; /* Seznamy sousedu vetvenı */char podezrely[MAXN]; /* Je do daneho vetvenı pripojen dum mafiana? */int hlidek; /* Potrebny pocet hlıdek */

void nacti_vstup(void) {int i, a, b;int tmp_ptr[MAXN];

Page 108: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

106 Riešenia celoštátneho kola kategórie A

/* Nacteme stoky */fscanf(in, “%d %d“, &n, &p);memset(deg, 0, n*sizeof(int));for (i = 0; i < n-1; i++) {

fscanf(in, “%d %d“, &a, &b);a--; b--;e[i][0] = a;e[i][1] = b;deg[a]++;deg[b]++;

}

/* Vytvorıme seznamy sousedu a nastavıme spravne jejich pocatky */edge_ptr[0] = 0;for (i = 1; i < n; i++)

edge_ptr[i] = edge_ptr[i-1]+deg[i-1];memset(tmp_ptr, 0, n*sizeof(int));for (i = 0; i < n-1; i++) {

neib[edge_ptr[e[i][0]]+tmp_ptr[e[i][0]]++] = e[i][1];neib[edge_ptr[e[i][1]]+tmp_ptr[e[i][1]]++] = e[i][0];

}

/* Nacteme seznam mafianu */for (i = 0; i < p; i++) {

fscanf(in, “%d“, &a);a--;podezrely[a] = 1;

}}

/* Spocte pocet hlıdek pro T_v, vratı 1, pokud je T_v nehlıdana. */int hledej(int v, int rodic) {int i, nehlidanych = 0;

/* Projdeme vsechny sousedy, ze kterych k nam vede stoka, a zjistıme situaci */for (i = 0; i < deg[v]; i++)

if (neib[edge_ptr[v]+i] != rodic)nehlidanych += hledej(neib[edge_ptr[v]+i], v);

/* Musıme vetvenı v hlıdat? *//* To je treba bud’ pokud mame alespon 2 nehlıdane sousedy (pak je treba* izolovat mafiany z nich), nebo pokud ve ’v’ sıdlı mafian a mame alespon* jednoho nehlıdaneho souseda. */

if (nehlidanych > 1 || (podezrely[v] && nehlidanych > 0)) {hlidek++;return 0;

}/* Jinak nemusıme hlıdat, jen vratıme, jestli je T_v nehlıdany */return nehlidanych || podezrely[v];

}

Page 109: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia celoštátneho kola kategórie A 107

int main(void) {in = fopen(“policie.in“, “r“);out = fopen(“policie.out“, “w“);nacti_vstup();hledej(0,0);fprintf(out, “%d\n“, hlidek);return 0;

}

A-III-5 Rybka Julka

Najjednoduchším správnym riešením by bolo postupne pre každý čas t =1, 2, 3, . . . spočítať množinu všetkých políčok, kde sa Julka môže v danom časenachádzať.Ak Mt je množina tých políčok, kde mohla byť Julka v čase t, množinu

Mt+1 ľahko zostrojíme z množiny Mt. Stačí pridať tie políčka, ktoré susedia snejakým políčkom z Mt a majú teplotu takú, že tam Julka smie v (t + 1)-ejsekunde preplávať. A naopak, vyhodíme tie políčka, ktoré už sú pre Julku prílišhorúce.Časom buď narazíme na také T , žeMT bude obsahovať cieľové políčko, alebo

zistíme, že aktuálna množina MT je prázdna. V prvom prípade sme práve našlinajrýchlejšiu cestu do cieľa, v druhom sa nám práve Julka uvarila.Takéto riešenie vieme ľahko implementovať tak, aby malo časovú zložitosť

O(RST ), kde R, S sú rozmery rybníka a T je čas, kedy prestaneme hľadať.Myšlienka efektívnejšieho riešenia:Lepšie riešenie bude založené na nasledujúcom pozorovaní: Pre každé políčko

nám stačí vedieť, ako najrýchlejšie (a kadiaľ) sa naň vieme dostať. Totiž ak sarozhodneme, že naša trasa povedie cez nejaké konkrétne políčko, nemá zmyselprísť tam inou ako najrýchlejšou cestou.Pre každé políčko [r, s] budeme teda chcieť spočítať hodnotu c(r, s) – naj-

menší počet sekúnd, po ktorom vieme byť na tomto políčku. (Navyše si budemepamätať aj smer, odkiaľ sem vedie jedna možná najrýchlejšia cesta.)

Na počítanie týchto hodnôt použijeme Dijkstrov algoritmus na hľadanienajkratšej cesty v grafe.Myšlienka je nasledovná: Všetky možné políčka budeme mať rozdelené do

dvoch množín: H budú hotové políčka, pre ktoré už vieme správnu hodnotuc(r, s), a S budú ešte spracúvané políčka.

Page 110: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

108 Riešenia celoštátneho kola kategórie A

Pre každé políčko [r, s] v S bude aktuálna hodnota c(r, s) predstavovať naj-menší čas, v akom sa vieme na políčko [r, s] dostať, ak ideme len cez políčka vH. (Prípadne c(r, s) =∞, ak žiadna takáto cesta neexistuje).Na začiatku nie je hotové žiadne políčko, teda H = ∅. Zjavne c(Jr, Js) = 0

a pre ostatné políčka je c(r, s) =∞.Zvyšok algoritmu bude prebiehať v kolách. V každom kole nájdeme v mno-

žine S jedno políčko, o ktorom vieme dokázať, že čas najkratšej cesty doň je užspočítaný správne. Toto políčko zakaždým presunieme do H a upravíme naj-lepšie časy pre políčka, ktoré zostali v S. Akonáhle sa cieľové políčko dostanemedzi hotové, môžeme skončiť.

Ako teda nájsť v množine S políčko, ktoré už môžeme presunúť medzi ho-tové? Jednoducho vyberieme z množiny S to políčko [r, s], ktoré má najmenšiuhodnotu c(r, s). (Ak by takých bolo viac, tak ľubovoľné z nich.) Tvrdíme, žehodnota c(r, s) pre toto políčko je už správna.Prečo? Všimnime si všetky možné spôsoby, ako sa dostať na políčko [r, s].

Už sme zobrali do úvahy všetky cesty, ktoré používajú len políčka z H. Každázo zvyšných ciest teda musí ísť cez aspoň jedno iné políčko [r′, s′] ∈ S. Lenževieme, že už c(r′, s′) ≥ c(r, s), a teda žiadna takáto cesta nebude rýchlejšia akoc(r, s).Políčko [r, s] teda prehlásime za hotové a presunieme ho z S do H.Teraz ešte zostáva upraviť hodnoty c(r, s) pre políčka, ktoré zostali v S. To

je ale jednoduché: Jediné políčka, kde sa niečo mohlo zmeniť, sú susedia políčka[r, s]. Tam pribudla možnosť, že najrýchlejší spôsob, ako sa dostať na takétopolíčko, je práve cez [r, s].Jednoducho teda prejdeme všetkých (nanajvýš štyroch) susedov políčka [r, s].

Pre každého suseda p = [rp, sp]: Ak p patrí do H, nič sa nedeje. Ak patrí doS, nová hodnota c(rp, sp) bude minimum z doterajšej hodnoty a z hodnotyc(r, s) + t, kde t je čas potrebný na presun z [r, s] na [rp, sp].(Čas t potrebný na presun závisí od c(r, s) a od teplôt oboch políčok. Z

týchto údajov ho vieme ľahko vypočítať v konštantnom čase.)Implementácia efektívnejšieho riešenia:Sú v princípe dva rôzne spôsoby, ako Dijkstrov algoritmus implementovať.Ten jednoduchší a priamočiarejší vyzerá nasledovne: použijeme dve polia

rozmerov rovnakých ako má rybník. V jednom si pre každé políčko budemepamätať, či už je hotové, v druhom aktuálne hodnoty c(r, s).Nájsť nové políčko, ktoré treba presunúť do H, vieme v čase O(RS) tak, že

prezrieme všetky políčka a nájdeme najlepšie z nich. Zvyšok kola, teda upraviť

Page 111: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia celoštátneho kola kategórie A 109

hodnoty c pre susedov, už vieme v konštantnom čase.Keďže v každom kole presunieme do H jedno políčko, kôl bude rádovo toľko

ako políčok. Celková časová zložitosť takéhoto riešenia je teda O(R2S2).

Je zjavné, že najpomalšou časťou predchádzajúcej implementácie je výbernového hotového políčka. Zbytočne znova a znova prechádzame všetky políčka.Nešlo by to lepšie?Čo by to bola za rečnícka otázka, keby odpoveď nebola „ánoÿ. Použijeme

dátovú štruktúru nazývanú halda. (Podrobný popis haldy nebudeme uvádzať,v prípade záujmu ho nájdete napr. v Programátorskej liahni, rovnako ako ajpodrobnejší popis tejto implementácie Dijkstrovho algoritmu.)V halde si budeme pamätať políčka množiny S, zoradené podľa doteraz

zisteného času cesty do nich. Takto vieme nové hotové políčko vybrať v časeO(log(RS)).Keď teraz získame pre nejakého suseda nový, lepší čas, jednoducho vložíme

do haldy pre tohto suseda nový záznam s týmto časom. (Netrápi nás, že tenstarý tam niekde zostane, lebo ten nový vyberieme skôr.) Každú takúto úpravuvieme teda spraviť v čase O(log(RS)).Podarilo sa nám teda vylepšiť trvanie jedného kola z O(RS) na O(log(RS)),

a tým časovú zložitosť celého algoritmu na O(RS log(RS)).

Program uvedený v listingu namiesto nami uvedeného triku na upravovanievzdialeností susedov používa inú metódu: pamätá si, kde v halde sa nachádzazáznam pre ktoré políčko, a keď sa nejakémuj políčku zmenší vzdialenosť, „pre-bubleÿ týmto políčkom v halde dohora.

Listing programu:program rybka;

const MAXM=1000;MAXN=1000;INFTY=3000000;

type PPole=ˆTPole;TPole=record

x,y:longint;halda:longint;t,c:longint;zpole:PPole;

end;

var m,n,x1,y1,x2,y2,t1,t2:longint; { zadane parametry }

Page 112: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

110 Riešenia celoštátneho kola kategórie A

rybnik:array[1..MAXM,1..MAXN] of TPole; { pole rybnıka }halda:array[1..MAXM*MAXN] of PPole; { halda v poli }velhaldy:longint;

procedure prehod(pos1:longint; pos2:longint); { prehod’ v halde dve pole }var tmp:PPole;begin

halda[pos1]ˆ.halda:=pos2;halda[pos2]ˆ.halda:=pos1;tmp:=halda[pos1];halda[pos1]:=halda[pos2];halda[pos2]:=tmp;

end;

procedure upravhaldu(var pole:TPole); { sniz hodnotu c(x,y) pole v halde }var hpos:longint;begin

hpos:=pole.halda;while (hpos>1) and (halda[hpos]ˆ.c < halda[hpos div 2]ˆ.c) do begin

prehod(hpos,hpos div 2);hpos:=hpos div 2;

end;end;

function vyberzhaldy:PPole; { vyber z haldy pole s nejnizsım c(x,y) }var hpos,minpos:longint;

hotovo:boolean;begin

if velhaldy=0 thenvyberzhaldy:=nil

else beginvyberzhaldy:=halda[1];halda[1]:=halda[velhaldy];halda[1]ˆ.halda:=1;dec(velhaldy);hotovo:=false;hpos:=1;repeat

{ bud’ uz jsme na spodku haldy }if (hpos*2>velhaldy) then hotovo:=true{ nebo mame jen jednoho potomka }else if (hpos*2=velhaldy) then begin

hotovo:=true;if (halda[hpos]ˆ.c>halda[hpos*2]ˆ.c) then

prehod(hpos,hpos*2);end{ nebo mame dva potomky }else begin

minpos:=hpos;if (halda[minpos]ˆ.c>halda[hpos*2]ˆ.c) then

Page 113: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Riešenia celoštátneho kola kategórie A 111

minpos:=hpos*2;if (halda[minpos]ˆ.c>halda[hpos*2+1]ˆ.c) then

minpos:=hpos*2+1;if (minpos=hpos) then

hotovo:=trueelse begin

prehod(hpos,minpos);hpos:=minpos;

end;end;

until hotovo;end;

end;

procedure vypis(var f:text; var pole:TPole);begin

if pole.zpole<>nil then beginvypis(f,pole.zpoleˆ);if pole.c-pole.zpoleˆ.c>1 then

write(f,pole.c-pole.zpoleˆ.c-1,’ ’);if pole.x>pole.zpoleˆ.x then write(f,’V ’);if pole.x<pole.zpoleˆ.x then write(f,’Z ’);if pole.y>pole.zpoleˆ.y then write(f,’J ’);if pole.y<pole.zpoleˆ.y then write(f,’S ’);

end;end;

procedure vylepsipole(var ktere:TPole; var odkud:TPole);var cek:longint;begin

{ jak dlouho musım pockat, nez se pole dost ohreje? }cek:=t1-(odkud.c+ktere.t);if cek<0 then cek:=0;{ jedna se o cılove pole? pokud ano, vubec necekej }if (ktere.x=x2) and (ktere.y=y2) then begin

ktere.c:=odkud.c+1;ktere.zpole:=@odkud;upravhaldu(ktere);

end{ kdyz pockam tolik, bude to ok na tomto i cılovem poli?

je to lepsı cesta? }else if (odkud.c+cek+odkud.t<=t2) and (odkud.c+cek+ktere.t+1<=t2)

and (ktere.c>odkud.c+cek+1) then beginktere.c:=odkud.c+cek+1;ktere.zpole:=@odkud;upravhaldu(ktere);

end;end;

var min:PPole;

Page 114: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

112 Riešenia celoštátneho kola kategórie A

hotovo:boolean;f1,f2:text;i,j:longint;

beginassign(f1,’rybka.in’); reset(f1);assign(f2,’rybka.out’); rewrite(f2);readln(f1,n,m,t1,t2);readln(f1,y1,x1,y2,x2);for j:=1 to n do

for i:=1 to m do beginread(f1,rybnik[i,j].t);rybnik[i,j].x:=i;rybnik[i,j].y:=j;rybnik[i,j].c:=INFTY;rybnik[i,j].zpole:=nil;rybnik[i,j].halda:=velhaldy+1;halda[velhaldy+1]:=@rybnik[i,j];inc(velhaldy);

end;rybnik[x1,y1].c:=0;upravhaldu(rybnik[x1,y1]);

{ hlavnı smycka vyberu z haldy }hotovo:=false;repeat

min:=vyberzhaldy;{ bud’ uz v halde nic k pridanı nenı }if (min=nil) or (minˆ.c=INFTY) then begin

writeln(f2,’Chudinka Julka!’);hotovo:=true;

end{ nebo vybıram cılove pole }else if (minˆ.x=x2) and (minˆ.y=y2) then begin

hotovo:=true;vypis(f2,rybnik[x2,y2]); { At’ zije Julka! }

end{ nebo je to nejake obecne pole }else begin

if minˆ.x>1 thenvylepsipole(rybnik[minˆ.x-1,minˆ.y],minˆ);

if minˆ.y>1 thenvylepsipole(rybnik[minˆ.x,minˆ.y-1],minˆ);

if minˆ.x<M thenvylepsipole(rybnik[minˆ.x+1,minˆ.y],minˆ);

if minˆ.y<N thenvylepsipole(rybnik[minˆ.x,minˆ.y+1],minˆ);

end;until hotovo;close(f1); close(f2);

end.

Page 115: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Výsledky krajského kola kategórie A

(Toto je spoločná výsledková listina po koordinácii bodovania, na základeporadia v tejto výsledkovej listine boli najlepší riešitelia pozvaní na celoštátnekolo.)

Meno Ročník, škola 1. 2. 3. 4. Σ1. Vladimír Boža 3 Gym. Tatarku Poprad 10 4 7 9 30Jozef Jirásek 4 Gym. Zbrojničná Košice 10 3 7 10 30

3. Ondrej Mikuláš 4 Gym. Haličská Lučenec 7 10 7 0 244. Marcel Ďuriš 4 Gym. P. Horova Michalovce 7 3 3 9 22Ján Jerguš 4 Gym. Alejová Košice 4 1 7 10 22Tomáš Kočiský 3 Gym. Grösslingová BA 4 1 7 10 22Michal Szabados 4 ŠPMND BA 10 2 10 22

8. Peter Herman 4 Gym. Jura Hronca BA 7 4 7 1 19Pavol Vaľkovič Gym. Zlaté Moravce 10 2 7 0 19

10. Milan Laslop Gym. Nedožerského Prievidza 4 5 7 2 18Adam Okruhlica 4 Gym. Jura Hronca BA 2 4 2 10 18

12. Samuel Brezáni 4 Gym. Rajec 8 2 7 0 17Peter Hlavatý 3 Gym. Jura Hronca BA 8 2 7 17Michal Sudolský 4 Gym. Tajovského B. Bystrica 10 7 0 17

15. Dominika Fedáková 3 Gym. Stará Ľubovňa 6 4 6 0 16Peter Hrinčár 3 Gym. Tatarku Poprad 9 4 3 0 16Jakub Končok 3 Gym. Haličská Lučenec 6 10 16Peter Ondrúška 3 SPŠ Dubnica nad Váhom 5 3 6 2 16

19. Michal Danilák 4 Gym. Hubeného BA 7 2 6 0 15Lenka Matejovičová 3 Gym. Grösslingová BA 9 4 2 15

21. Timotej Betina 4 Gym. L. Stöckela Bardejov 7 0 5 2 14Juraj Danko 4 Gym. P. de Coubertina PN 6 1 7 0 14

23. Samuel Hapák 3 Gym. Grösslingová BA 2 9 2 13Martin Višňovec 4 Gym. Lettricha Martin 8 1 2 2 13

25. Balázs Kezes 4 Gym. Nové Zámky 2 2 7 1 12

Page 116: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

114 Výsledky krajského kola kategórie A

Meno Ročník, škola 1. 2. 3. 4. ΣMatúš Kotry 4 Gym. Párovská Nitra 2 4 6 12Tomáš Kovačovský 4 Gym. Jura Hronca BA 2 3 7 12Juraj Kušnier 3 Gym. Bánovce nad Bebravou 2 2 6 2 12Martin Sucha 3 Gym. Jura Hronca BA 2 10 12

30. Kristína Čevorová 4 ŠPMND BA 2 7 2 11František Hajnovič 4 Gym. Jura Hronca BA 4 7 11Alena Košinárová 3 Gym. Grösslingová BA 2 2 7 0 11Pavol Otto 3 Gym. sv. Františka Žilina 2 7 2 11Martin Podolák 4 Gym. Grösslingová BA 2 2 7 0 11Ivan Srba 4 Gym. Liptovský Hrádok 7 2 2 11Tomáš Zábojník 4 Gym. Liptovský Hrádok 8 1 2 11Lukáš Zdechovan 4 Gym. Tajovského B. Bystrica 8 1 2 11

38. Pavol Blaho 3 Gym. Jura Hronca BA 9 1 10Michal Kučiš 4 Gym. Čadca 1 3 4 2 10Kristián Nagy 3 Gym. Jura Hronca BA 2 4 2 2 10Peter Nikodem 3 Gym. Školská Spiš. Nová Ves 1 7 2 10Michal Petrucha 2 Gym. Metodova BA 2 6 2 10

43. Daniel Bene 3 Gym. Haličská Lučenec 2 7 0 9Ivan Buštor 4 Gym. Jura Hronca BA 8 1 9Albert Herencsár 2 Gym. maď. Galanta 2 7 9

46. Róbert Balent Gym. Lettricha Martin 2 6 8Miroslav Brada 3 Gym. Varšavská Žilina - Vlčince 2 2 2 2 8Dušan Ďurech Gym. 17. novembra Topoľčany 2 4 2 8Martin Hanes 3 Gym. P. Horova Michalovce 2 0 6 0 8Maroš Kasinec 3 Gym. P. Horova Michalovce 2 0 6 0 8Luboš Kuboň 2 Gym. Jura Hronca BA 2 4 2 8Andrej Pančík 4 Gym. Tajovského B. Bystrica 5 1 2 0 8Lucia Simanová 3 Gym. Grösslingová BA 2 2 2 2 8Emília Szabadosová 3 ŠPMND BA 7 1 8Tibor Szabó 4 Gym. Šuleka Komárno 2 4 2 0 8Danica Zajacová 4 Gym. Jura Hronca BA 2 4 2 8

57. Jaroslav Böhmer 3 Gym. Školská Spiš. Nová Ves 2 1 4 0 7Michal Ferko 4 Gym. Jura Hronca BA 2 3 2 0 7

Page 117: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Výsledky krajského kola kategórie A 115

Meno Ročník, škola 1. 2. 3. 4. ΣMarcel Švec 4 Gym. Jura Hronca BA 5 2 7

60. Peter Korcsok 3 Gym. Mládežnícka Šahy 2 1 2 1 6Ladislav Rampášek 4 Gym. Jura Hronca BA 2 2 2 6Matúš Zamborský Gym. Hollého Trnava 2 2 2 6

63. Jaroslav Brdjar 4 Gym. Alejová Košice 3 0 1 1 5Peter Drábik 4 Gym. Čadca 2 1 2 5Ján Hreha 4 Gym. Liptovský Hrádok 1 2 2 5Marcel Kanta Gym. Hubeného BA 2 2 1 5Ján Percsök Gym. Daxnerova R. Sobota 1 1 2 1 5Adam Saleh 3 Gym. Jura Hronca BA 2 2 1 5Jakub Tomaga 4 Gym. P. Horova Michalovce 2 1 2 0 5András Varga 3 Gym. H. Selyeho Komárno 2 1 2 0 5Radoslav Zajonc Gym. Športová Nové Mesto n.V. 2 2 1 0 5Martin Zruban Gym. Hollého Trnava 2 1 2 0 5

73. Róbert Barsa 4 Gym. Poštová Košice 2 0 2 0 4Katarína Gajdziková 4 Gym. Daxnera V.n. Topľou 2 0 2 0 4Miroslav Piter Gym. Svidník 2 0 2 0 4Michal Pristáš 3 Gym. Daxnera V.n. Topľou 2 0 2 0 4Branislav Uljan 4 Gym. Poštová Košice 1 0 1 2 4

78. Tomáš Benedikti 3 Gym. P. Horova Michalovce 1 0 2 0 3Jakub Bokšanský 4 SPŠ Spišská Nová Ves 1 0 2 0 3Filip Hanes 4 Gym. Tajovského B. Bystrica 1 2 0 3Peter Vida Gym. Nedožerského Prievidza 3 3

82. Erik Tilňák 4 Gym. Humenné 0 0 0 1 183. Michal Klein 3 Gym. Školská Spiš. Nová Ves 0 0 0 0 0

Page 118: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Výsledky celoštátneho kola kategórie A

Meno Ročník, škola 1. 2. 3. 4. 5. Σ1. Michal Danilák 4 G. Hubeného BA 7 9 10 15 13 542. Vladimír Boža 3 G. Tatarku Poprad 6 9 7 15 9 463. Samuel Hapák 3 G. Grösslingová BA 7 8 4 15 9 434. Peter Herman 4 G. Jura Hronca BA 4 5 7 15 6 375. Jozef Jirásek 4 G. Zbrojničná Košice 6 7 10 4 8 356. Ondrej Mikuláš 4 G. Haličská Lučenec 6 6 4 15 0 317. Peter Ondrúška 3 SPŠ Dubnica nad Váhom 6 8 10 1 4 298. Ján Jerguš 4 G. Alejová Košice 3 1 7 0 11 229. Michal Szabados 4 ŠPMND BA 4 9 7 1 0 2110. Peter Hlavatý 3 G. Jura Hronca BA 2 4 1 – 9 16Adam Okruhlica 4 G. Jura Hronca BA 7 8 1 – 0 16

12. Tomáš Kočiský 3 G. Grösslingová BA 5 7 1 0 0 13Milan Laslop G. Nedožerského Prievidza 1 6 2 3 1 13Balázs Kezes 4 G. Nové Zámky 6 3 1 0 3 13

15. Peter Hrinčár 3 G. Tatarku Poprad 5 5 1 1 0 12Marcel Ďuriš 4 G. P. Horova Michalovce 4 6 1 1 0 12

17. Matúš Kotry 4 G. Párovská Nitra 2 6 0 3 – 1118. Juraj Kušnier 3 G. Bánovce nad Bebravou 0 6 2 2 – 10Tomáš Kovačovský 4 G. Jura Hronca BA 1 6 0 3 0 10Michal Sudolský 4 G. Tajovského BB 0 6 2 2 0 10

21. Juraj Danko 4 G. P. de Coubertina PN 0 6 2 0 0 8Kristína Čevorová 4 ŠPMND BA 0 6 2 0 – 8Alena Košinárová 3 G. Grösslingová BA 3 4 1 0 0 8Martin Sucha 3 G. Jura Hronca BA 0 6 0 1 1 8

25. František Hajnovič 4 G. Jura Hronca BA 6 0 1 0 – 7Lenka Matejovičová 3 G. Grösslingová BA 2 3 2 0 0 7

27. Dominika Fedáková 3 G. Stará Ľubovňa 0 5 1 0 0 6Jakub Končok 3 G. Haličská Lučenec 0 3 0 3 – 6

29. Martin Višňovec 4 G. Lettricha Martin 0 3 1 0 – 4

Page 119: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Výsledky Česko-Poľsko-Slovenského

prípravného stretnutia CPSPC 2007

Meno (štát) 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Σ1. Tomasz Kulczynski (pl) 100 0 27 100 – 66 100 – 100 0 100 100 6932. Jaroslaw Gomulka (pl) 100 30 – 80 – 5 40 20 40 0 100 60 4753. Piotr Niedzwiedz (pl) 30 – – 60 – 1 100 10 100 0 50 100 4514. Vladimír Boža (sk) 40 20 36 10 30 38 40 0 40 0 100 60 4145. Maciej Klimek (pl) – 50 – 60 – 16 40 – 40 0 100 100 4066. Jakub Kallas (pl) 100 – – 100 – 34 – – – – 100 35 3697. Miroslav Klimoš (cz) 0 40 0 0 95 4 40 0 30 0 40 70 3198. Jozef Jirásek (sk) – – – 10 – 53 40 40 40 0 100 10 2939. Peter Ondrúška (sk) – – – – – 53 0 0 40 0 100 75 26810. Michal Danilák (sk) – 0 27 0 – 58 40 0 30 – 100 – 25511. Pavel Klavík (cz) 0 10 54 – 0 4 40 – 10 0 100 0 21812. Marcin Kurczych (pl) – 0 9 – – – – 100 0 – 100 – 20913. Lukáš Lánský (cz) 60 – 18 – 0 69 20 0 40 0 0 0 20714. Josef Pihera (cz) 70 0 0 10 0 22 20 20 0 0 50 – 19215. Alena Košinárová (sk) – 30 0 0 – 23 30 – 20 – 50 – 15316. Roman Smrž (cz) 0 0 0 – – 8 40 0 – 0 100 0 14817. Libor Plucnar (cz) – 10 – – – 20 40 – 10 – 50 – 13018. Peter Hlavatý (sk) – – 0 – – 34 20 0 – – – – 54

Page 120: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Výsledky Medzinárodnej olympiády

v informatike, IOI 2007

V roku 2007 sa Medzinárodná olympiáda v informatike (IOI) konala v dňoch15. až 22. augusta v chorvátskom Záhrebe. Súťaže sa zúčastnilo 285 súťažiacichz takmer 80 krajín celého sveta.Ako lídri zastupujúci našu krajinu pri hlasovaniach sa tejto IOI zúčastnili

RNDr. Andrej Blaho a Juliana Lipková, obaja z FMFI UK v Bratislave. Akočlen medzinárodnej odbornej komisie (ISC) sa tejto IOI zúčastnil Mgr. MichalForišek z FMFI UK v Bratislave.Našu krajinu tento rok reprezentovala táto štvorica stredoškolákov: Vladimír

Boža z Gymnázia D. Tatarku v Poprade, Michal Danilák z Gymnázia Hube-ného v Bratislave, Peter Ondrúška z SPŠ v Dubnici nad Váhom a Jozef Jirásekz Gymnázia Zbrojničná v Košiciach. Výsledky našich súťažiacich uvádzame zhr-nuté v tabuľke.

Meno Počet bodov31. Michal Danilák 366 – striebro57. Vladimír Boža 311 – striebro78. Peter Ondrúška 275 – bronz

Jozef Jirásek

Page 121: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

Výsledky Stredoeurópskej olympiády

v informatike, CEOI 2007

V roku 2007 sa Stredoeurópska olympiáda v informatike (CEOI) konala vdňoch 1. až 7. júla v neďalekom Brne, ČR. Súťaže sa zúčastnili tímy zo siedmichkrajín: Českej republiky, Chorvátska, Maďarska, Nemecka, Poľska, Rumunskaa Slovenska.Ako lídri zastupujúci našu krajinu pri hlasovaniach sa tejto CEOI zúčastnili

doc. RNDr. Gabriela Andrejková, CSc. z ÚI PF UPJŠ v Košiciach a PeterPerešíni z FMFI UK v Bratislave.Našu krajinu tento rok reprezentovala tá istá štvorica stredoškolákov ako

na IOI: Vladimír Boža z Gymnázia D. Tatarku v Poprade, Michal Danilák zGymnázia Hubeného v Bratislave, Peter Ondrúška z SPŠ v Dubnici nad Váhoma Jozef Jirásek z Gymnázia Zbrojničná v Košiciach. Výsledky našich súťažiacichuvádzame zhrnuté v tabuľke.

Meno Počet bodov12. Vladimír Boža 338 – bronz17. Jozef Jirásek 24620. Peter Ondrúška 22026. Michal Danilák 177

Page 122: Dvadsiatydruhýročník Olympiádyvinformatikeoi.sk/rocenky/oi22.pdf · 2013. 11. 24. · RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OI Dvadsiaty druhý ročník

RNDr. Michal Forišek, Bc. Jakub Kováč, Slovenská komisia OIDvadsiaty druhý ročník Olympiády v informatikeVydal: Iuventa, Bratislava, 2008119 strán, náklad 300 výtlačkovNeprešlo jazykovou úpravouISBN 80-8072-053-3