220 likes | 312 Views
Osaka pod Godzillou Príklad prvého kola zimnej časti 26. ročníka KSP. Lu káš Miňo 3Ib lukassmino@gmail.com. Osaka pod Godzillou. Príklad prvého kola zimnej časti 26. ročníka KSP 20 bodov, kategória O V Osake postavili nový rad mrakodrapov.
E N D
Osaka pod GodzillouPríklad prvého kola zimnej časti 26. ročníka KSP Lukáš Miňo 3Ib lukassmino@gmail.com
Osaka pod Godzillou • Príklad prvého kola zimnej časti 26. ročníka KSP • 20 bodov, kategória O • V Osake postavili nový rad mrakodrapov. • Keď sa o tom dozvedela Godzilla, tak si povedala, že je ten pravý čas na ich označkovanie (To znamená zanechanie odtlačku nohy na streche). • Tak vyliezla na ten najľavejší a rozhliadla sa. • Zistila, že nemôže označkovať všetky, lebo vie skákať len na nižšie mrakodrapy. • Zato sa vie rozbehnúť a preto vie skočiť ľubovoľne ďaleko (Jedine, že by cestou stretla vyšší mrakodrap a narazila do neho). • Avšak Godzilla po boji s Mechagodzillou je unavená a preto keď sa raz rozbehne, tak už nesmie zastať (presnejšie, ak zastane, tak sa nerozbehne znova). • Pomôžte Godzille zistiť, koľko najviac mrakodrapov vie označkovať.
Úloha • V prvom riadku je N, čo je počet mrakodrapov. • V druhom riadku je N čísiel v[1], v[2], … v[N], ktoré označujú výšky jednotlivých mrakodrapov. • Godzilla stojí na mrakodrape 1. • Godzila vie skočiť z mrakodrapu i na mrakodrap j práve vtedy, ak platia nasledovné podmienky: • i < j -- nemôže skočiť na predchádzajúci mrakodrap. • V[j] > v[i]-- nemôže skočiť na vyšší mrakodrap. • Pre všetky k také, že i < k < j, platí: v[k]<=v[i] -- počas skoku nemôže ,,preletieť'' cez nejaký vyšší mrakodrap. • Vašou úlohou je napísať program, ktorý zo zadaných údajov zistí, koľko najviac skokov môže Godzilla spraviť.
Príklad • Vstup • N = 1010 9 8 7 8 9 6 4 2 9 • Výstup • 5 • Poznámka: • Najskôr skočí na mrakodrap 2 potom na mrakodrap 6, 7, 8 a 9 a teda bude vo výškach 10 9 9 6 4 2 .
1. Možnosť • Vyskúšať všetky možnosti • Vstup: • 10 9 8 7 8 9 6 4 2 9 • Možnosti: • 10 (ok), 10 9 (ok), 10 8 (ok), 10 7 (ok), 10 8 (ok), 10 9 (ok), 10 6 (ok), 10 4 (ok), 10 2 (ok), 10 9 (ok), 10 9 8 (ok), …, 10 8 7 (ok), …, 10 9 8 7 8 (zle), ..., 10 9 8 7 8 9 6 4 2 9 (zle).
Alternatíva • Previesť úlohu na graf 8 7 8 9 9 10 6 4 2 9
Problém? • Existuje cyklus? • Nie, lebo godzila skáče od najľavejšieho okraja smerom doprava
2. možnosť • Prehľadávanie do šírky 9 8 7 8 … 7 9 7 8 8 … 10 9 … 6 4 2 9
3. možnosť • Backtrack • Vstup - 10 9 8 7 8 9 6 4 2 9 8 7 9 8 10 9 6 4 2 4 2 2 …
4. možnosť • Topologicky utriediť a použiť dynamické programovanie • Vstup - 10 9 8 7 8 9 6 4 2 9 • 9 8 7 4 5 3 10 6 2 1 (indexy) • 2 4 6 7 8 8 9 9 9 10 (výšky budov) • 0 1 2 3 3 4 0 4 5 6 (počet skokov)
4. možnosť • Pozor na poradie pri triedení budov rovnakých výšok (záleží na poradí indexov) • Správne: • 9 8 7 4 5 3 10 6 2 1 (indexy) • 2 4 6 7 8 8 9 9 9 10 (výšky budov) • 0 1 2 3 3 4 0 4 5 6 (počet skokov) • Nespávne: • 9 8 7 4 3 5 2 6 10 1 (indexy) • 2 4 6 7 8 8 9 9 9 10 (výšky budov) • 0 1 2 3 4 3 5 3 0 6 (počet skokov) • Dúfam, že vidno rozdiel !!!!
Pre ktorú možnosť sa rozhodnuť? • Faktory: • Z neznámych príčin nie je obmedzený počet vstupov N (pri väčine úloh je rozsah N spomenutý) – prečo? Neviem • Musíme aj tak preskúmať všetky cesty • Najideálnejší algoritmus: Backtrack
Ako implementovať backtrack? • Popis myšlienky: • Pokúšame sa prejsť z najľavejšej budovy na najpravejšiu • Cestou zisťujeme, či sa dá na danú budovu skočiť • Ak áno, tak skočíme a pokračujeme predchádzajúcim krokom • Ak nie, tak sa vrátime o budovu späť a na túto už neskáčeme. Skočíme na inú • Cestou si zapamätáme počet skokov a maximálny skok • Nakoniec vypíšeme maximálny skok
Čo si pamätať? • Výšky budov • Počet skokov na každú budovu (aby sme sa vedeli vrátiť späť) • Maximálny skok • Pozíciu i-tej budovy • Počet budov
Popis algoritmu • Pokial i-ta budova < počet budov rob: • Ak výška ďalšej budovy <= výška i-tej budovy, tak skoč na ďalšiu budovu a zvýš počet skokov o 1 • Inak zruš danú budovu, zníž počet budov o 1 a vráť sa na predchádzajúcu budovu • Ak je počet skokov > počet maximálnych skokov, tak maxímalny počet je tento počet skokov • Vráť sa na krok 1
Ukážka algoritmu v C++ • while(i<pocetBudov){ • if(v[i]>=v[i+1]){ • i++; • skoky[i]=skoky[i-1]+1; • }else{ • skoky[i]=0; • for(int j=i;j<pocetBudov;j++) v[j]=v[j+1]; • i--; • pocetBudov--; • } • if(skoky[i]>maximum) maximum=skoky[i]; • }
Odhad časovej zložitosti • while(i<pocetBudov){ • if(v[i]>=v[i+1]){ • i++; • skoky[i]=skoky[i-1]+1; • }else{ • skoky[i]=0; • for(int j=i;j<pocetBudov;j++){ • v[j]=v[j+1]; • } • i--; • pocetBudov--; • } } O(N*N) = O(N^2)
Odhad pamäťovej zložitosti • Pole výšok budov (integer) • Pole skokov budov (integer)
Zdroj • http://www.ksp.sk/ksp2.0/wiki/Zadania/26-1z