66. ročník Matematické olympiády 2016/2017
|
|
- Nikola Šmídová
- před 5 lety
- Počet zobrazení:
Transkript
1 66. ročník Matematické olympiády 2016/2017 Řešení úloh ústředního kola kategorie P 1. soutěžní den P-III-1 Bizoní rezervace Zadány jsou alespoň tři přímky v obecné poloze a hledáme konvexní obal všech jejich průsečíků. V řešení budeme využívat standardních pojmy a postupy z oblasti geometrických algoritmů. Nebudeme je zde detailně odvozovat, všechny je najdete přehledně popsané v Programátorské kuchařce KSP.* Jednoduché řešení Povšimněme si, že průsečíků N přímek je pouze N (N 1)/2 < N 2. Můžeme pro každou dvojici přímek určit jejich průsečík a na závěr spočítat jejich konvexní obal. Průsečík dvou přímek zvládneme najít v konstantním čase a konvexní obal K bodů v čase O(K log K). Celková asymptotická časová složitost tohoto přímočarého algoritmu je O(N 2 log(n 2 )), což je rovno O(N 2 log N), neboť log(n 2 ) = 2 log N. Rychlejší řešení Nejprve popíšeme jednoduše znějící algoritmus a až poté ukážeme jeho správnost. Začneme seřazením všech přímek vzestupně podle jejich směrnic, tedy podílu B i /A i. V případě, že A i = 0 (jedná se o přímku rovnoběžnou s osou x), uvažujeme směrnici nekonečnou a zařadíme takovou přímku na konec. Následně spočteme průsečík každých dvou přímek, které jsou sousední v našem pořadí a navíc uvažujeme, že první přímka sousedí s tou poslední (uspořádání je cyklické). Na závěr vezmeme všechny tyto průsečíky a nalezneme jejich konvexní obal standardním algoritmem zmíněným výše. Nalezený konvexní obal popisuje hledanou ohradu s nejmenším obvodem, která obsahuje také všechny ostatní průsečíky přímek. Z uvedeného algoritmu není na první pohled vůbec jasné, proč by měl fungovat. Budeme muset ukázat, že průsečík dvou přímek, které nejsou sousední v cyklickém seznamu přímek uspořádaném podle směrnic, leží v nalezeném konvexním obalu. Uvažme jednu takovou dvojici přímek p, q a jejich průsečík X. Protože tyto přímky nejsou sousední, tak pokud budeme procházet cyklický seznam přímek postupně od přímky p do přímky q, nalezneme mezi nimi alespoň jednu jinou přímku. Vezměme libovolnou takovou přímku r. Podobně procházíme-li seznamem od přímky q do přímky p, nalezneme nějakou přímku s. Označme průsečíky přímky r s přímkami p, q postupně R p, R q a průsečíky přímky s s přímkami p, q postupně S p, S q (každé dvě přímky se protínají v jednom bodě a všechny průsečíky jsou ze zadání různé). Dále ukážeme, že průsečík X přímek p a q leží na přímce mezi dvěma jinými průsečíky dvou zadaných přímek. Pro spor předpokládejme, že tomu tak není a zaměřme se na polopřímky XR p a XR q. Pokud by bod S p ležel na polopřímce XR p a zároveň bod S q ležel na polopřímce XR q, pak by v našem cyklickém uspořádání přímek podle směrnic byla přímka s také na cestě od přímky p do přímky q, což je * 1
2 ve sporu s její volbou. Jeden z bodů S p, S q musí tedy ležet na polopřímce opačné a bod X leží buď na úsečce R p S p nebo na úsečce R q S q, a proto ho nebylo potřeba uvažovat při tvorbě konvexního obalu. Popsaný algoritmus se skládá ze dvou kroků a jak řazení N přímek dle směrnic, tak i hledání konvexního obalu N bodů lze implementovat s asymptotickou složitostí O(N log N). Paměťová složitost našeho algoritmu je lineární v N. #include <cstdio> #include <algorithm> #define MAX_N int A[MAX_N], B[MAX_N], C[MAX_N]; int N; /* * Porovná směrnice A[i] / B[i] a vrátí true, pokud směrnice * přímky p je menší nez směrnice přímky q. Abychom nemuseli * převádět celá čísla na double a ztrácet tím přesnost, upravíme * zkoumanou nerovnost A[p] / B[p] < A[q] / B[q] do tvaru, kde * se pouze násobí. Při násobení je třeba být opatrný na přetečení. * Poznamenejme, že přímka s B[i] = 0 bude zařazena na konec. */ bool porovnej_smernice(int p, int q) return (long long)a[p] * B[q] < (long long)a[q] * B[p]; // Indexy přímek uspořádané vzestupně podle jejich směrnic. int primky[max_n]; /* * Hledáme průsečík přímek * p: A[p] * x + B[p] * y + C[p] = 0 * q: A[q] * x + B[q] * y + C[q] = 0 * Řešíme soustavu dvou lineárních rovnic o dvou neznámých. */ 2
3 void prusecik_primek(int p, int q, double &x, double &y) x = (double)(b[q] * C[p] - B[p] * C[q]) / (B[q] * A[p] - B[p] * A[q]); y = (double)(a[q] * C[p] - A[p] * C[q]) / (A[q] * B[p] - A[p] * B[q]); // Průsečíky přímek sousedících v cyklickém uspořádání. double prusecik_x[max_n], prusecik_y[max_n]; /* * Následuje standardní algoritmus na výpočet konvexního obalu bodů v rovině. * Nejprve uspořádáme všechny body vzestupně podle souřadnice x. * Poté je procházíme v tomto pořadí a průběžně tvoříme horní a dolní * půl-obaly a nakonec sloučíme obě části do jednoho obalu. * * Funkci v programu volame jedinkrát, a proto pro jednoduchost načítáme * vstup i ukládáme výstup do globálních polí. * Vstup: prusecik_x, prusecik_y * Výstup: obal délky delka_obalu obsahuje indexy průsečíků */ int obal[max_n], delka_obalu; int horni[max_n], delka_horni, dolni[max_n], delka_dolni; /* Primárně porovnáváme podle y, sekundárně podle x. */ bool porovnej_pruseciky(int a, int b) if (prusecik_x[a]!= prusecik_x[b]) return prusecik_x[a] < prusecik_x[b]; return prusecik_y[a] < prusecik_y[b]; int pruseciky[max_n]; /* Třetí složka vektorového součinu vektoru PQ a PR. */ long long vektorovy_soucin(int P, int Q, int R) return (prusecik_x[q] - prusecik_x[p]) * (prusecik_y[r] - prusecik_y[p]) - (prusecik_y[q] - prusecik_y[p]) * (prusecik_x[r] - prusecik_x[p]); void konvexni_obal() for (int i = 0; i < N; ++i) pruseciky[i] = i; std::sort(pruseciky, pruseciky + N, porovnej_pruseciky); delka_horni = delka_dolni = 0; for (int i = 0; i < N; ++i) while ( delka_horni > 1 && vektorovy_soucin(i, horni[delka_horni - 1], horni[delka_horni - 2]) <= 0 ) delka_horni--; while ( delka_dolni > 1 && vektorovy_soucin(i, dolni[delka_dolni - 1], dolni[delka_dolni - 2]) >= 0 ) delka_dolni--; horni[delka_horni++] = i; dolni[delka_dolni++] = i; 3
4 delka_obalu = 0; for (int i = 0; i < delka_horni; ++i) obal[delka_obalu++] = horni[i]; for (int i = delka_dolni - 2; i >= 1; --i) obal[delka_obalu++] = dolni[i]; int main(int argc, char *argv[]) // Načteme vstup. scanf("%d", &N); for (int i = 0; i < N; ++i) scanf("%d%d%d", A + i, B + i, C + i); // Uspořádáme přímky vzestupně dle jejich směrnic. for (int i = 0; i < N; ++i) primky[i] = i; std::sort(primky, primky + N, porovnej_smernice); // Spočítáme průsečíky každých dvou přímek sousedních směrnic. for (int i = 0; i < N - 1; ++i) prusecik_primek(i, i + 1, prusecik_x[i], prusecik_y[i]); prusecik_primek(n - 1, 0, prusecik_x[n - 1], prusecik_y[n - 1]); // Spočítáme kondexní obal. konvexni_obal(); // Vypíšeme výsledek. for (int i = 0; i < delka_obalu; ++i) printf("%.6lf %.6lf\n", prusecik_x[obal[i]], prusecik_y[obal[i]]); return 0; P-III-2 Hostina Předpokládejme nejprve, že nikdo nepracuje přes půlnoc. Nechť t 1 je nejmenší čas, v němž jednomu ze zaměstnanců Z skončí pracovní doba. Hostimír nutně musí rozdat koláčky nejpozději v čase t 1, jinak by nepohostil zaměstnance Z. Na druhou stranu, určitě se mu vyplatí rozdat koláčky co nejpozději (tím může pohostit navíc další zaměstnance, kteří začínají později). Je tedy pro něj nejvýhodnější poprvé koláčky rozdat v čase t 1. Obdobnou úvahou dospějeme k tomu, že podruhé by měl rozdat koláčky v nejmenším čase t 2, v němž skončí pracovní doba nějakému zaměstnanci, který začal pracovat až po čase t 1, atd. V proměnné t si budeme udržovat čas, v němž Hostimír naposledy rozdal koláčky (na začátku t = 1). Stačí si tedy zaměstnance setřídit vzestupně dle konce jejich pracovní doby a postupně je procházet; pokaždé, když narazíme na zaměstnance, který začal pracovat po čase t, rozdáme další dávku koláčků v okamžiku, kdy mu skončí pracovní doba (a hodnotu t nastavíme na tento čas). Časová složitost tohoto algoritmu je dominována složitostí třídění, tedy O(n log n). Co když ale někdo přes půlnoc pracuje? Kdybychom znali nějaký čas t 0, v němž Hostimír rozdá koláčky, pak ze vstupu můžeme vyhodit všechny zaměstnance pracující v čase t 0 a na zbylé aplikovat výše popsaný algoritmus (čas t 0 hraje roli půlnoci můžeme například všechny pracovní doby přepočítat na jejich vzdálenost od času t 0 ). 4
5 Mohli bychom tedy vyzkoušet všechny možné časy t 0 stačí si rozmyslet, že opět stačí jako t 0 volit konce pracovních dob zaměstnanců, je tedy pouze n možností. Z nich si vybereme tu, která potřebuje nejméně dávek koláčků. Tím dostáváme algoritmus s časovou složitostí O(n 2 log n), který snadno vylepšíme na O(n 2 ), uvědomíme-li si, že je zbytečné konce pracovních dob třídit pokaždé znova stačí si jednou určit jejich cyklické pořadí. Jak by šel tento algoritmus ještě vylepšit? Uvědomme si, že algoritmus z předchozího odstavce zbytečně počítá stejné věci opakovaně. Jestliže Hostimír rozdá koláčky v nějakém čase t 1, následující čas t 2, v němž znovu rozdá koláčky (tj. první konec pracovní doby zaměstnance, který začal pracovat po čase t 1 ), je vždy stejný nezávisle na vybraném počátečním čase t 0 (samozřejmě s výjimkou případu, že bychom na čas t 0 narazili dříve než na konec pracovní doby tohoto zaměstnance, v tomto případě již jsou všichni zaměstnanci pohoštěni). Předpočítejme si tedy pro každý relevantní čas t 1 (opět stačí uvažovat konce pracovních dob) odpovídající čas t 2 ; postupujeme přitom podobně jako ve druhém odstavci, pouze při určení tohoto času nepřenastavíme t na t 2, ale na nejbližší další konec pracovní doby po t 1. Výsledky si uložíme do pole nasledujici, které je indexované čísly zaměstnanců; prvek nasledujici[i] tedy odpovídá času, v němž končí pracovní doba zaměstnance i. Jako hodnotu nasledujici[i].zamestnanec si uložíme číslo zaměstnance, jehož konec pracovní doby je t 2. Kromě toho si jako hodnotu nasledujici[i].doba uložíme počet milisekund mezi časy t 1 a t 2 (tedy t 2 t 1 je-li t 2 > t 1, nebo m t 1 + t 2, je-li t 2 < t 1, tj. nastane-li mezi časy t 1 a t 2 půlnoc). Nyní bychom mohli algoritmus z třetího odstavce přeformulovat takto: projdeme všechny zaměstnance a vyzkoušíme jako t 0 volit konce jejich pracovních dob. Nechť zkoušíme jako t 0 volit jako konec pracovní doby zaměstnance i 0. Pak inicializujeme i = i 0 a opakovaně provádíme i =nasledujici[i].zamestnanec, dokud součet dob uložených v navštívených prvcích pole nasledujici nedosáhne alespoň délky dne m. Počet opakování odpovídá počtu časů, v nichž Hostimír rozdá koláčky. Může se zdát, že jsme si moc nepomohli, přímočará implementace popsaného algoritmu opět má časovou složitost O(n 2 ). Nicméně počet iterací pro každé i 0 můžeme určit i efektivněji. Nejprve si postupně předpočítejme, kam a za jakou dobu se z každého i dostaneme po 2, 4, 8,..., 2 k iteracích, kde k = log 2 n. To zvládneme v čase O(n log n) abychom zjistili, kam se z i dostaneme po 2 t+1 iteracích, stačí zjistit, kam se dostaneme po 2 t iteracích a kam se odtamtud dostaneme po dalších 2 t iteracích, a tyto hodnoty již máme předpočítané. S těmito předpočítanými informacemi můžeme nutný počet iterací pro každé i zjistit v čase O(log n) půlením intervalů: Nejprve zjistíme, zda se po 2 k iteracích dostaneme na dobu alespoň m, a pokud ne, o těchto 2 k iterací se posuneme. Poté totéž opakujeme pro 2 k 1,..., 4, 2, 1 iterací. Celková časová i paměťová složitost výsledného algoritmu je O(n log n). 5
6 #include <stdio.h> #include <stdlib.h> #define MAXN #define MAXLOG 20 static int n, m; static struct zamestnanec int a, b; zamestnanci[maxn]; static struct int zamestnanec, doba; nasledujici[maxlog][maxn]; static int cas_mezi(int f, int t) return (t - f + m) % m; static int pracovni_doba(const struct zamestnanec *z) return cas_mezi(z->a, z->b); static int dle_konce(const void *z1, const void *z2) const struct zamestnanec *zz1 = z1; const struct zamestnanec *zz2 = z2; if (zz1->b == zz2->b) return pracovni_doba(zz1) - pracovni_doba(zz2); return zz1->b - zz2->b; static int v_intervalu(struct zamestnanec *interval, int cas) if (interval->a <= interval->b) return interval->a <= cas && cas <= interval->b; return cas >= interval->a cas <= interval->b; int main (void) int i, t, e, doba; scanf("%d%d", &n, &m); for (i = 0; i < n; i++) scanf("%d%d", &zamestnanci[i].a, &zamestnanci[i].b); qsort(zamestnanci, n, sizeof(struct zamestnanec), dle_konce); // Pro zjednodušení: končí-li více zaměstnanců ve stejnou dobu, stačí // uvažovat toho z nich s nejkratší pracovní dobou. e = 1; for (i = 1; i < n; i++) if (zamestnanci[i].b!= zamestnanci[i - 1].b) zamestnanci[e++] = zamestnanci[i]; n = e; 6
7 e = 0; doba = 0; for (t = 0; t < n; t++) while (v_intervalu(zamestnanci + e, zamestnanci[t].b)) int ne = (e + 1) % n; doba += cas_mezi(zamestnanci[e].b, zamestnanci[ne].b); e = ne; if (doba >= m) /* Speciální případ: všichni pracují ve stejný čas (konec pracovní doby zaměstnance t). */ printf("1\n"); return 0; nasledujici[0][t].zamestnanec = e; nasledujici[0][t].doba = doba; doba -= cas_mezi(zamestnanci[t].b, zamestnanci[(t + 1) % n].b); int log = 0; while ((1 << log) <= n) log++; for (i = 1; i < log; i++) for (t = 0; t < n; t++) int m = nasledujici[i - 1][t].zamestnanec; nasledujici[i][t].zamestnanec = nasledujici[i - 1][m].zamestnanec; nasledujici[i][t].doba = nasledujici[i - 1][t].doba + nasledujici[i - 1][m].doba; int min_potreba = n; for (t = 0; t < n; t++) int potreba = 1; doba = 0; e = t; for (i = log - 1; i >= 0; i--) if (doba + nasledujici[i][e].doba < m) doba += nasledujici[i][e].doba; potreba += (1 << i); e = nasledujici[i][e].zamestnanec; if (potreba < min_potreba) min_potreba = potreba; printf("%d\n", min_potreba); return 0; 7
8 P-III-3 Stromochod Procházení stromu Nejprve si pořídíme sadu funkcí na přerušované procházení stromu. Budeme chtít navštvívit všechny vrcholy zvoleného podstromu, a přitom si kdykoliv moci odskočit do jiného podstromu. Všechny vrcholy uspořádáme v pre-orderu, to znamená, že kořen bude první, pak všechny vrcholy v jeho levém podstromu a nakonec všechny vrcholy v pravém podstromu. Vrcholy uvnitř podstromů jsou opět uspořádány pre-orderem. V procházeném podstromu budeme udržovat právě jeden vrchol označený jako aktivní. Chceme umět následující operace: Init zavoláme v kořeni podstromu a kořen se stane aktivním. Enter zavoláme v kořeni podstromu a stromochod se přesune do aktivního vrcholu. Leave zavoláme v aktivním vrcholu a stromochod se vrátí do kořene podstromu. Next zavoláme v aktivním vrcholu, stromochod se přesune do následníka tohoto vrcholu v pre-orderu a učiní ho aktivním; kdyby už žádný následník neexistoval, zastaví se v kořeni podstromu a oznámí neúspěch. Reset zavoláme v aktivním vrcholu, chceme-li procházení ukončit předčasně. Strom tedy procházíme posloupností Init, Next, Next,..., přičemž si kdykoliv můžeme operací Leave odskočit mimo podstrom a pomocí Enter se opět vrátit. Operace budou využívat značek ve vrcholech stromu. Především budeme udržovat stav vrcholu: aktivní vrchol bude ve stavu 1, vrcholy na cestě z kořene k aktivnímu vrcholu budou označeny 2 nebo 3 podle toho, jestli cesta pokračuje doleva nebo doprava. Všechny ostatní vrcholy budou mít stav 0. Také si budeme pamatovat booleovskou proměnnou koren, podle které poznáme, že se nacházíme v kořeni podstromu. procedure Init; Postačí nastavit značky a vrátit se V.koren := true; V.stav := 1; procedure Enter; Projdeme po cestě zaznamenané ve stavech while V.stav <> 1 do if V.stav=2 then jdi_l else jdi_p; end 8
9 procedure Leave; Vracíme se nahoru, než narazíme na kořen while not V.koren do jdi_o; function Next: boolean; if ex_l then Existuje-li levý syn, je následníkem V.stav := 2; jdi_l; end else if ex_r then Zkusíme pravého syna V.stav := 3; jdi_p; end else Jsme v listu => vracíme se nahoru repeat V.stav := 0; jdi_o; until V.koren or ((V.stav=2) and ex_p); if (V.stav=2) and ex_p then V.stav := 3; Vrchol s pravým synem => jdeme doprava jdi_p; end else Přišli jsme zprava do kořene => končíme V.stav := 0; V.koren := false; Next := false; exit; V.stav := 1; Aktivujeme nový vrchol Next := true; procedure Reset; Projdeme se z aktivního vrcholu do kořene a smažeme značky while not V.koren do V.stav := 0; jdi_o; V.stav := 0; V.koren := false; Rozebereme časovou složitost operací. Init zvládneme v konstantním čase. Enter, Leave a Reset stojí lineárně se vzdáleností mezi kořenem a aktivním vrcholem. Next může stát až lineárně s hloubkou podstromu, ale všechna volání Next dohromady v celém podstromu trvají lineárně s počtem vrcholů v podstromu, neboť každý vrchol navštívíme nejvýše třikrát. 9
10 Jednoduché řešení Dokonalou vyváženost stromu můžeme testovat následovně. Budeme procházet všechny vrcholy stromu (prohledáním do hloubky ze studijního textu, nebo třeba právě popsaným mechanismem). V každém vrcholu chceme porovnat velikosti podstromů. Kdyby nám stačilo ověřit, že podstromy jsou úplně stejně velké, stačilo by je procházet paralelně tedy střídat kroky v obou podstromech a zkontrolovat, zda obě procházení skončí současně. Nejprve bychom tedy zavolali Init na obou podstromech a pak opakovaně Enter, Next a Leave v obou podstromech na střídačku. Máme-li připustit i jedničkový rozdíl ve velikostech, pak v případech, kdy jedno procházení skončilo dříve než druhé, ověříme, že druhé udělá nejvýše jeden krok navíc. Následující program se řídí tímto principem. Jen se navíc musíme vypořádat s tím, že levý či pravý syn může úplně chybět. Také si všimněte, že procházení stromu ve vnějším cyklu nijak neinterferuje s vnitřními cykly, protože vnitřní cykly navštěvují pouze vrcholy pod aktivním vrcholem vnějšího cyklu. var next_l, next_p, next_l_old: boolean; Init; V.ok := false; repeat next_l, next_p budou říkat, která prohledávání ještě pokračují if ex_l then next_l := true; jdi_l; Init; jdi_o; end else next_l := false; if ex_p then next_p := true; jdi_p; Init; jdi_o; end else next_p := false; while next_l or next_p do Jeden krok v levém podstromu next_l_old := next_l; if next_l then jdi_l; Enter; if Next then Leave; if not next_p then halt; Pravý skončil o 2 dřív end else next_l := false; Levý právě skončil jdi_o; A teď totéž napravo if next_p then jdi_p; Enter; if Next then Leave; if not next_l_old then halt; end else next_p := false; jdi_o; 10
11 until not Next; V.ok := true; Jaká je časová složitost tohoto řešení? Postupně navštívíme n vrcholů, pro každý z nich projdeme všech nejvýše n vrcholů v podstromech a každý krok procházení trvá až lineárně s hloubkou podstromu, což může být až O(n). Celkem tedy O(n 3 ). Malé vylepšení s velkými důsledky Všimneme si, že předchozí algoritmus je tak pomalý pouze ve velmi specifických případech (mohou-li vůbec nastat). Dokážeme, že kdykoliv je strom dokonale vyvážený, přijdeme na to mnohem rychleji. Nejprve nahlédneme, že každý dokonale vyvážený strom má logaritmickou hloubku. Vskutku: pokud se vydáme po libovolné cestě z kořene do listu, velikost podstromu, který leží pod námi, se s každým krokem zmenší alespoň dvakrát. Nejvýše po L = log 2 n krocích tedy musíme dojít do listu. Nyní to využijeme při výpočtu časové složitosti. Hladiny stromu očíslujeme od 0 do L zdola nahoru. Na i-té hladině leží nejvýše 2 L i vrcholů, každý z nich je kořenem podstromu hloubky nejvýše i o maximálně 2 i vrcholech. V tomto podstromu každý Next, Enter i Leave trvá O(i), takže zkoumáním podstromu strávíme čas O(i 2 i ). Zkontrolovat všechny podstromy zakořeněné na i-té hladině proto trvá O(2 L i i 2 i ) = O(2 L i). Jelikož 2 L n a i log 2 n, můžeme předchozí výraz omezit O(n log n). Na všech L hladinách tedy trávíme dohromady čas O(n log 2 n). V nevyváženém stromu se nám nicméně může stát, že nějaký podstrom bude příliš hluboký, takže jeho kontrola bude mnohem pomalejší. Poradíme si tak, že podstromy budeme kontrolovat zdola nahoru (třeba upraveným prohledáváním do hloubky) a jakmile narazíme na nevyvážený podstrom, okamžitě skončíme. Pak si totiž můžeme být jistí, že levý i pravý pod-podstrom nevyváženého podstromu jsou vyvážené (jinak bychom chybu objevili dřív). Proto se i v nevyváženém případě hloubky od logaritmu liší nejvýše o 1. Takto upravený algoritmus má složitost O(n log 2 n) i v nejhorším případě. Počítadla Předchozí řešení lze ještě zrychlit, byť se tím trochu zkomplikuje. Vrcholy v podstromech začneme doopravdy počítat. Stromochod sice nemá proměnné pro neomezená čísla, ale můžeme čísla ukládat do vrcholů stromu ve dvojkové soustavě: každý vrchol si v proměnné bit zapamatuje jeden bit čísla. Bity budou po sobě následovat v pre-orderu; začneme nejnižším bitem a za nejvyšší bit přidáme hodnotu 1 jako značku konce čísla. Číslo vyjadřující počet vrcholů v podstromu se přitom vždy vejde do vrcholů tohoto podstromu, neboť x > log 2 x pro všechna x 1. Jen pozor na to, že pokud x = 1, nevejde se už za číslo koncová 1. Konec čísla tedy poznáme buď podle 1, nebo podle toho, že Next vrátil false. 11
12 Strom budeme procházet do hloubky. Kdykoliv se budeme vracet z nějakého vrcholu, spočítáme číslo vyjadřující počet jeho potomků. Ten získáme sečtením už spočítaných počtů potomků levého a pravého syna. Při té příležitosti také počty potomků porovnáme, abychom ověřili vyváženost. Zkusíme napsat podprogramy pro zvýšení čísla o 1 a porovnání čísel na rovnost. procedure BinaryInc; var p: integer; Init; p := 1; while (p = 1) and (V.bit >= 0) do p := p + V.bit; V.bit := p mod 2; p := p div 2; Next; if V.bit < 0 then V.bit := 1; Next; V.bit := -1; Reset; function BinaryCmp: boolean; Porovná číslo v levém a pravém podstromu var x, y: integer; vysledek: boolean; next_l, next_p: boolean; if ex_l then jdi_l; Init; jdi_o; next_l := true; end else next_l := false; if ex_p then jdi_p; Init; jdi_o; next_p := true; end else next_p := false; repeat if next_l then jdi_l; Enter; x := V.bit; if Next then Leave else next_l := false; jdi_o; end else x := -1; if next_p then jdi_p; Enter; y := V.bit; if Next then Leave else next_p := false; end else y := -1; if (x<0) and (y<0) then BinaryCmp := true; break; if x <> y then BinaryCmp := false; break; until false; if next_l then jdi_l; Enter; Reset; jdi_o; if next_p then jdi_p; Enter; Reset; jdi_o; Potřebujeme nicméně poznat, že dvě čísla se liší o jedničku. Jednoduchý způsob, jak to zařídit, je zkombinovat porovnávání se sčítáním. Během porovnávání si budeme představovat, že jsme jedno z čísel zvýšili o jedničku, ale výsledek nebudeme nikam ukládat, pouze s ním porovnávat. 12
13 Zbývá umět sečíst čísla uložená v synech do jednoho čísla uloženého v otci. Nabízí se nejprve přičíst pravé číslo k levému a poté výsledek přesunout do otce. Samotné přesunutí není problém: stačí každý bit přesunout do jeho předka v preorderu, na což stačí do našeho procházecího mechanismu doplnit operaci Prev pro přesun do předchůdce fungující podobně jako Next. Mohlo by se ovšem stát, že výsledek se do levého podstromu nevejde. Proto raději nejprve přesuneme a poté sčítáme. Jeden sčítanec tedy bude uložen v kořeni a levém podstromu, druhý v pravém podstromu. Spočítejme složitost. Podstrom na i-té hladině (opět číslujeme zespoda) má hloubku i, takže Prev, Next a spol. trvají O(i). Pracujeme přitom s čísly o logaritmickém počtu bitů vzhledem k velikosti podstromů, tedy O(log 2 i ) = O(i). Jedna operace s čísly tedy trvá O(i 2 ). Sečtením přes jednu hladinu dostaneme O(2 L i i 2 ) = O(n/2 i i 2 ), sečtením přes celý strom pak: ( L ( ( n O 2 i i2)) = O n i=0 L i=0 ) ( i 2 2 i O n log n L i=0 ) i 2 i. Poslední inkluze platí díky tomu, že i je vždy nejvýše log n. Suma na její pravé straně je přitom shora omezena konstantou.* Složitost celého algoritmu je tedy O(n log n). Mělká počítadla Algoritmus s počítadly se překvapivě dá ještě zlepšit. Místo abychom bity počítadla ukládali v pre-orderu, uložíme je po hladinách. Tím pádem přístup k jednotlivým bitům k-bitového počítadla bude trvat pouze O(log k), zatímco předtím byl lineární v hloubce podstromu, kde je počítadlo uloženo. Jedna aritmetická operace pak stojí O(k log k). Technické detaily popíšeme pouze zhruba. V podstromu budeme udržovat zarážku nastavenou na určitou hladinu: všechny vrcholy na této hladině opatříme speciální značkou a operaci Next naučíme, aby se o značku zarazila. Kdykoliv nám dojde místo na počítadlo, posuneme zarážku o hladinu níže. Naopak při přesouvání čísla ze syna do otce potřebujeme posunout i zarážku. Přesun zarážky přitom stojí O(k), takže si ho můžeme dovolit provést konstanta-krát na jednu aritmetickou operaci. Přepočítáme složitost. Na i-té hladině jsou počítadla i-bitová, takže jedna operace stojí O(log i). V součtu přes celou hladinu dostaneme O(2 L i i log i). Sečtením přes všechny hladiny dostaneme: ( L ( n ) ) ( O 2 i i log i = O n i=0 L i=0 ) ( i log i 2 i O n log log n L i=0 ) i 2 i. * To je nerovnost známá z rozboru budování haldy zdola nahoru. Důkaz najdete například v kapitole o haldách na 13
14 Inkluze plyne z toho, že i log n, takže log i log log n. Suma na pravé straně je opět omezena konstantou, takže jsme složitost celého algoritmu odhadli výrazem O(n log log n). Překvapení na závěr Nápady účastníků ústředního kola nás inspirovaly k dalšímu řešení, které pracuje v lineárním čase a překvapivě se obejde bez porovnávání velikostí podstromů. Je založené na opakování redukčních kroků. Jeden takový krok buďto strom zamítne jako nevyvážený, nebo ho upraví na menší strom, který je vyvážený pravě tehdy, když byl vyvážený původní strom. Nejprve dokážeme pomocné tvrzení o struktuře dokonale vyvážených stromů, které je připodobňuje k úplným binárním stromům z domácího kola. Lemma: Dokonale vyvážený strom je buďto úplný, nebo z něj smazáním nejnižší hladiny úplný strom vznikne. Důkaz: Mějme dokonale vyvážený strom o h hladinách, který není úplný. Hladině h 1 budeme říkat koruna stromu. Hladiny od kořene do koruny doplníme virtuálními vrcholy na úplný strom. Pokud v koruně neleží žádné virtuální vrcholy, nemohou ležet ani jinde, takže tvrzení lemmatu platí. V opačném případě pokračujeme: Vrcholy koruny, které mají syny o hladinu níže, nazveme pupeny. Nyní označíme s nejhlubší vrchol stromu, pod kterým je alespoň jeden virtuální vrchol a alespoň jeden pupen. Vrchol s sám není ani virtuální, ani pupen. Všimneme si, že v žádném podstromu pod vrcholem s nemohou být současně virtuální vrcholy a pupeny, protože by s bylo ještě možné posunout níž. Existuje tedy jeden podstrom (řekněme levý), v němž jsou virtuální vrcholy, ale nejsou pupeny. V opačném podstromu (řekněme pravém) se naopak nachází pupeny, ale ne virtuální vrcholy. Nyní se podívejme na hladiny těchto podstromů ležící (neostře) nad korunou. V pravém podstromu jsou všechny tyto hladiny plné a pod nejnižší z nich je alespoň jeden list z h-té hladiny. V levém naopak alespoň jeden vrchol chyběl (byl doplněn virtuálním) a na h-té hladině neleží žádné vrcholy. Proto se velikosti obou podstromů liší aspoň o 2, takže strom nemohl být vyvážený. Nyní popíšeme redukční krok. Nejprve otestujeme, zda strom splňuje podmínku z lemmatu. To můžeme ověřit v čase O(n) jednoduchou úpravou algoritmu na testování úplnosti stromu z domácího kola. Algoritmus nám vyznačí poslední úplnou hladinu (korunu) a zkontroluje, zda pod ní leží pouze listy. Poté strom očešeme : podíváme se na vrcholy koruny a pokud je vrchol koruny list, odstraníme ho. Pokud má nějaké syny, odstraníme jednoho ze synů. Očesání jistě můžeme provést v lineárním čase. Všimneme si, že tím celkově ze stromu ubylo přesně tolik vrcholů, kolik jich leželo v koruně. Také si všimneme, že z obou podstromů pod libovolným vnitřním vrcholem v musel ubýt stejný počet vrcholů mezi v a korunou je totiž strom úplný. Očesaný strom je tedy dokonale vyvážený právě tehdy, když takový byl původní strom. Nyní dokážeme, že očesáním ubyla alespoň čtvrtina všech vrcholů. Kdyby strom byl úplný, v koruně leží polovina všech vrcholů (±1), takže bychom polovinu vrcholů 14
15 smazali. Není-li úplný, pod korunou leží nejvýše tolik vrcholů, kolik jich je ve zbytku stromu, takže koruna tvoří alespoň čtvrtinu vrcholů. Opakováním redukčního kroku tedy získáváme stromy velké nejvýše (3/4) n, (3/4) 2 n,..., až po strom konstantní velikosti, kde jistě umíme dokonalou vyváženost testovat v konstantním čase. Každým stromem strávíme čas lineární s jeho velikostí, takže celkově algoritmus běží v čase O(n i (3/4)i ). Tato suma je geometrická řada se součtem 1/(1 3/4) = 4. Celková složitost tedy činí O(n). 15
66. ročník Matematické olympiády 2016/2017
66. ročník Matematické olympiády 2016/2017 Úlohy ústředního kola kategorie P 1. soutěžní den Na řešení úloh máte 4,5 hodiny čistého času. Řešení každé úlohy pište na samostatný list papíru. Při soutěži
68. ročník Matematické olympiády 2018/2019
68. ročník Matematické olympiády 2018/2019 Řešení úloh krajského kola kategorie P P-II-1 Tulipány Budeme řešit o něco obecnější úlohu: dovolíme si předepsat, zda má na n-té pozici být tulipán, a pokud
68. ročník Matematické olympiády 2018/2019
68. ročník Matematické olympiády 2018/2019 Řešení úloh ústředního kola kategorie P 2. soutěžní den P-III-4 Výlet Abychom našli požadovaný výlet délky 4, stačí najít dvě hvězdy a a b, které mají dva společné
V každém kroku se a + b zmenší o min(a, b), tedy vždy alespoň o 1. Jestliže jsme na začátku dostali 2
Euklidův algoritmus Doprovodný materiál pro cvičení Programování I. NPRM044 Autor: Markéta Popelová Datum: 31.10.2010 Euklidův algoritmus verze 1.0 Zadání: Určete největšího společného dělitele dvou zadaných
Intervalové stromy. Představme si, že máme posloupnost celých čísel p 0, p 1,... p N 1, se kterou budeme. 1. Změna jednoho čísla v posloupnosti.
Intervalové stromy Představme si, že máme posloupnost celých čísel p 0, p 1,... p N 1, se kterou budeme průběžně provádět tyto dvě operace: 1. Změna jednoho čísla v posloupnosti. 2. Zjištění součtu čísel
Test prvočíselnosti. Úkol: otestovat dané číslo N, zda je prvočíslem
Test prvočíselnosti Úkol: otestovat dané číslo N, zda je prvočíslem 1. zkusit všechny dělitele od 2 do N-1 časová složitost O(N) cca N testů 2. stačí zkoušet všechny dělitele od 2 do N/2 (větší dělitel
66. ročník Matematické olympiády 2016/2017
66. ročník Matematické olympiády 016/017 Úlohy krajského kola kategorie P Krajské kolo 66. ročníku MO kategorie P se koná v úterý 17. 1. 017 v dopoledních hodinách. Na řešení úloh máte 4 hodiny čistého
Algoritmy I, složitost
A0B36PRI - PROGRAMOVÁNÍ Algoritmy I, složitost České vysoké učení technické Fakulta elektrotechnická v 1.01 Rychlost... Jeden algoritmus (program, postup, metoda ) je rychlejší než druhý. Co ta věta znamená??
68. ročník Matematické olympiády 2018/2019
68. ročník Matematické olympiády 2018/2019 Řešení úloh ústředního kola kategorie P 1. soutěžní den P-III-1 Půl království Pokud v hledané polorovině neleží všechny zadané body, můžeme bez újmy na obecnosti
Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 21.
Vyhledávání doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava Prezentace ke dni 21. září 2018 Jiří Dvorský (VŠB TUO) Vyhledávání 242 / 433 Osnova přednášky
Stromy, haldy, prioritní fronty
Stromy, haldy, prioritní fronty prof. Ing. Pavel Tvrdík CSc. Katedra počítačů FEL České vysoké učení technické DSA, ZS 2008/9, Přednáška 6 http://service.felk.cvut.cz/courses/x36dsa/ prof. Pavel Tvrdík
66. ročník Matematické olympiády 2016/2017
66. ročník Matematické olympiády 2016/2017 Úlohy domácího kola kategorie P Úlohy P-I-1 a P-I-2 jsou praktické, vaším úkolem v nich je vytvořit a odladit efektivní program v jazyce Pascal, C nebo C++. Řešení
Stromy. Jan Hnilica Počítačové modelování 14
Stromy Jan Hnilica Počítačové modelování 14 1 Základní pojmy strom = dynamická datová struktura, složená z vrcholů (uzlů, prvků) propojených hranami hrany chápeme jako orientované, tzn. vedou z uzlu A
Obecná informatika. Matematicko-fyzikální fakulta Univerzity Karlovy v Praze. Podzim 2012
Obecná informatika Přednášející Putovních přednášek Matematicko-fyzikální fakulta Univerzity Karlovy v Praze Podzim 2012 Přednášející Putovních přednášek (MFF UK) Obecná informatika Podzim 2012 1 / 18
Základní datové struktury III: Stromy, haldy
Základní datové struktury III: Stromy, haldy prof. Ing. Pavel Tvrdík CSc. Katedra počítačových systémů Fakulta informačních technologií České vysoké učení technické v Praze c Pavel Tvrdík, 2010 Efektivní
64. ročník matematické olympiády Řešení úloh krajského kola kategorie A
64. ročník matematické olympiády Řešení úloh krajského kola kategorie A 1. Středy stran AC, BC označme postupně, N. Střed kružnice vepsané trojúhelníku KLC označme I. Úvodem poznamenejme, že body K, L
Binární vyhledávací stromy pokročilé partie
Binární vyhledávací stromy pokročilé partie KMI/ALS lekce Jan Konečný 30.9.204 Literatura Cormen Thomas H., Introduction to Algorithms, 2nd edition MIT Press, 200. ISBN 0-262-5396-8 6, 3, A Knuth Donald
Informatika navazující magisterské studium Přijímací zkouška z informatiky 2018 varianta A
Informatika navazující magisterské studium Přijímací zkouška z informatiky 2018 varianta A Každá úloha je hodnocena maximálně 25 body. Všechny své odpovědi zdůvodněte! 1. Postavte na stůl do řady vedle
DobSort. Úvod do programování. DobSort Implementace 1/3. DobSort Implementace 2/3. DobSort - Příklad. DobSort Implementace 3/3
DobSort Úvod do programování Michal Krátký 1,Jiří Dvorský 1 1 Katedra informatiky VŠB Technická univerzita Ostrava Úvod do programování, 2004/2005 V roce 1980 navrhl Dobosiewicz variantu (tzv. DobSort),
Dijkstrův algoritmus
Dijkstrův algoritmus Hledání nejkratší cesty v nezáporně hranově ohodnoceném grafu Necht je dán orientovaný graf G = (V, H) a funkce, která každé hraně h = (u, v) H přiřadí nezáporné reálné číslo označované
5 Rekurze a zásobník. Rekurzivní volání metody
5 Rekurze a zásobník Při volání metody z metody main() se do zásobníku uloží aktivační záznam obsahující - parametry - návratovou adresu, tedy adresu, kde bude program pokračovat v metodě main () po skončení
Digitální učební materiál
Digitální učební materiál Číslo projektu: CZ.1.07/1.5.00/34.0548 Název školy: Gymnázium, Trutnov, Jiráskovo náměstí 325 Název materiálu: VY_32_INOVACE_145_IVT Autor: Ing. Pavel Bezděk Tematický okruh:
1 Lineární prostory a podprostory
Lineární prostory a podprostory Přečtěte si: Učebnice AKLA, kapitola první, podkapitoly. až.4 včetně. Cvičení. Které z následujících množin jsou lineárními prostory s přirozenými definicemi operací?. C
NPRG030 Programování I, 2018/19 1 / :03:07
NPRG030 Programování I, 2018/19 1 / 20 3. 12. 2018 09:03:07 Vnitřní třídění Zadání: Uspořádejte pole délky N podle hodnot prvků Měřítko efektivity: * počet porovnání * počet přesunů NPRG030 Programování
Úlohy krajského kola kategorie A
64. ročník matematické olympiády Úlohy krajského kola kategorie A 1. Je dán trojúhelník ABC s tupým úhlem při vrcholu C. Osa o 1 úsečky AC protíná stranu AB v bodě K, osa o 2 úsečky BC protíná stranu AB
Lingebraické kapitolky - Analytická geometrie
Lingebraické kapitolky - Analytická geometrie Jaroslav Horáček KAM MFF UK 2013 Co je to vektor? Šipička na tabuli? Ehm? Množina orientovaných úseček majících stejný směr. Prvek vektorového prostoru. V
Vyvažování a rotace v BVS, všude se předpokládá AVL strom
Vyvažování a rotace v BVS, všude se předpokládá AVL strom 1. Jednoduchá levá rotace v uzlu u má operační složitost a) závislou na výšce levého podstromu uzlu u b) mezi O(1) a Θ(n) c) závislou na hloubce
Reprezentace aritmetického výrazu - binární strom reprezentující aritmetický výraz
Reprezentace aritmetického výrazu - binární strom reprezentující aritmetický výraz (2 + 5) * (13-4) * + - 2 5 13 4 - listy stromu obsahují operandy (čísla) - vnitřní uzly obsahují operátory (znaménka)
Algoritmy a datové struktury
Algoritmy a datové struktury Stromy 1 / 32 Obsah přednášky Pole a seznamy Stromy Procházení stromů Binární stromy Procházení BS Binární vyhledávací stromy 2 / 32 Pole Hledání v poli metodou půlení intervalu
bin arn ı vyhled av an ı a bst Karel Hor ak, Petr Ryˇsav y 23. bˇrezna 2016 Katedra poˇ c ıtaˇ c u, FEL, ˇ CVUT
binární vyhledávání a bst Karel Horák, Petr Ryšavý 23. března 2016 Katedra počítačů, FEL, ČVUT Příklad 1 Naimplementujte binární vyhledávání. Upravte metodu BinarySearch::binarySearch. 1 Příklad 2 Mysĺım
Úlohy klauzurní části školního kola kategorie B
65. ročník matematické olympiády Úlohy klauzurní části školního kola kategorie B 1. Kolika způsoby je možno vyplnit čtvercovou tabulku 3 3 čísly,, 3, 3, 3, 4, 4, 4, 4 tak, aby součet čísel v každém čtverci
7. Geometrické algoritmy (sepsal Pavel Klavík)
7. Geometrické algoritmy (sepsal Pavel Klavík) Ukážeme si několik základních algoritmů na řešení geometrických problémů v rovině. Proč zrovna v rovině? Inu, jednorozměrné problémy bývají triviální a naopak
Definice. Vektorový prostor V nad tělesem T je množina s operacemi + : V V V, tj. u, v V : u + v V : T V V, tj. ( u V )( a T ) : a u V které splňují
Definice. Vektorový prostor V nad tělesem T je množina s operacemi + : V V V, tj. u, v V : u + v V : T V V, tj. ( u V )( a T ) : a u V které splňují 1. u + v = v + u, u, v V 2. (u + v) + w = u + (v + w),
INFORMATIKA. Vybrané podposloupnosti
INFORMATIKA Vybrané podposloupnosti (Úlohy z MO kategorie P, 30. část) PAVEL TÖPFER Matematicko-fyzikální fakulta UK, Praha V našem seriálu putujícím po zajímavých úlohách Matematické olympiády - kategorie
Základy algoritmizace a programování
Základy algoritmizace a programování Složitost algoritmů. Třídění Přednáška 8 16. listopadu 2009 Který algoritmus je "lepší"? Různé algoritmy, které řeší stejnou úlohu zbytek = p % i; zbytek = p - p/i*i;
Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 12.
Vyhledávání doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava Prezentace ke dni 12. září 2016 Jiří Dvorský (VŠB TUO) Vyhledávání 201 / 344 Osnova přednášky
Binární soubory (datové, typované)
Binární soubory (datové, typované) - na rozdíl od textových souborů data uložena binárně (ve vnitřním tvaru jako v proměnných programu) není čitelné pro člověka - všechny záznamy téhož typu (může být i
Algoritmizace a programování
Algoritmizace a programování Výrazy Operátory Výrazy Verze pro akademický rok 2012/2013 1 Operace, operátory Unární jeden operand, operátor se zapisuje ve většině případů před operand, v některých případech
Zpracoval: hypspave@fel.cvut.cz 7. Matematická indukce a rekurse. Řešení rekurentních (diferenčních) rovnic s konstantními koeficienty.
Zpracoval: hypspave@fel.cvut.cz 7. Matematická indukce a rekurse. Řešení rekurentních (diferenčních) rovnic s konstantními koeficienty. (A7B01MCS) I. Matematická indukce a rekurse. Indukční principy patří
Dynamické datové struktury III.
Dynamické datové struktury III. Halda. Tomáš Bayer bayertom@natur.cuni.cz Katedra aplikované geoinformatiky a kartografie, Přírodovědecká fakulta UK. Tomáš Bayer bayertom@natur.cuni.cz (Katedra aplikované
(4x) 5 + 7y = 14, (2y) 5 (3x) 7 = 74,
1. V oboru celých čísel řešte soustavu rovnic (4x) 5 + 7y = 14, (2y) 5 (3x) 7 = 74, kde (n) k značí násobek čísla k nejbližší číslu n. (P. Černek) Řešení. Z první rovnice dané soustavy plyne, že číslo
ANALYTICKÁ GEOMETRIE LINEÁRNÍCH ÚTVARŮ V ROVINĚ
ANALYTICKÁ GEOMETRIE LINEÁRNÍCH ÚTVARŮ V ROVINĚ Parametrické vyjádření přímky v rovině Máme přímku p v rovině určenou body A, B. Sestrojíme vektor u = B A. Pro bod B tím pádem platí: B = A + u. Je zřejmé,
Klauzurní část školního kola kategorie A se koná
56. ročník matematické olympiády Úlohy klauzurní části školního kola kategorie 1. rčete všechna reálná čísla s, pro něž má rovnice 4x 4 20x 3 + sx 2 + 22x 2 = 0 čtyři různé reálné kořeny, přičemž součin
Algoritmus pro hledání nejkratší cesty orientovaným grafem
1.1 Úvod Algoritmus pro hledání nejkratší cesty orientovaným grafem Naprogramoval jsem v Matlabu funkci, která dokáže určit nejkratší cestu v orientovaném grafu mezi libovolnými dvěma vrcholy. Nastudoval
IB108 Sada 1, Příklad 1 Vypracovali: Tomáš Krajča (255676), Martin Milata (256615)
IB108 Sada 1, Příklad 1 ( ) Složitost třídícího algoritmu 1/-Sort je v O n log O (n.71 ). Necht n = j i (velikost pole, které je vstupním parametrem funkce 1/-Sort). Lehce spočítáme, že velikost pole předávaná
Padovan heaps Vladan Majerech
Padovan heaps Vladan Majerech Základní princip velmi drahé porovnávání Porovnáváme jen když musíme (v podstatě veškerou práci dělá FindMin) Výsledky porovnávání nezahazujeme Nesmíme organizací porovnávání
Algoritmizace Dynamické programování. Jiří Vyskočil, Marko Genyg-Berezovskyj 2010
Dynamické programování Jiří Vyskočil, Marko Genyg-Berezovskyj 2010 Rozděl a panuj (divide-and-conquer) Rozděl (Divide): Rozděl problém na několik podproblémů tak, aby tyto podproblémy odpovídaly původnímu
Řazení. Uspořádat množinu prvků obsahujících klíč podle definovaného kriteria.
Řazení Problém řazení: Uspořádat množinu prvků obsahujících klíč podle definovaného kriteria. Až 30% času běžného počítače. Příklad: Mějme zjistit zda jsou v posloupnosti prvků, například celých čísel,
Řešení: PŘENESVĚŽ (N, A, B, C) = přenes N disků z A na B pomocí C
Hanojské věže - 3 kolíky A, B, C - na A je N disků různé velikosti, seřazené od největšího (dole) k nejmenšímu (nahoře) - kolíky B a C jsou prázdné - úkol: přenést všechny disky z A na B, mohou se odkládat
Časová a prostorová složitost algoritmů
.. Časová a prostorová složitost algoritmů Programovací techniky doc. Ing. Jiří Rybička, Dr. ústav informatiky PEF MENDELU v Brně rybicka@mendelu.cz Hodnocení algoritmů Programovací techniky Časová a prostorová
IB111 Úvod do programování skrze Python
Vyhledávání, řazení, složitost IB111 Úvod do programování skrze Python 2012 Otrávené studny 8 studen, jedna z nich je otrávená laboratorní rozbor dokáže rozpoznat přítomnost jedu ve vodě je drahý (je časově
Ukážeme si lineární algoritmus, který pro pevné k rozhodne, zda vstupní. stromový rozklad. Poznamenejme, že je-li k součástí vstupu, pak rozhodnout
Ukážeme si lineární algoritmus, který pro pevné k rozhodne, zda vstupní graf má stromovou šířku nejvýše k, a je-li tomu tak, také vrátí příslušný stromový rozklad. Poznamenejme, že je-li k součástí vstupu,
Poznámka. V některých literaturách se pro označení vektoru také používá symbolu u.
Vektory, operace s vektory Ž3 Orientovaná úsečka Mějme dvojici bodů, (na přímce, v rovině nebo prostoru), které spojíme a vznikne tak úsečka. Pokud budeme rozlišovat, zda je spojíme od k nebo od k, říkáme,
3. Prohledávání grafů
3. Prohledávání grafů Prohledání do šířky Breadth-First Search BFS Jde o grafový algoritmus, který postupně prochází všechny vrcholy v dané komponentě souvislosti. Algoritmus nejprve projde všechny sousedy
Výrazy a operátory. Operátory Unární - unární a unární + Např.: a +b
Výrazy a operátory i = 2 i = 2; to je výraz to je příkaz 4. Operátory Unární - unární a unární + Např.: +5-5 -8.345 -a +b - unární ++ - inkrement - zvýší hodnotu proměnné o 1 - unární -- - dekrement -
12. Lineární programování
. Lineární programování. Lineární programování Úloha lineárního programování (lineární optimalizace) je jedním ze základních problémů teorie optimalizace. Našim cílem je nalézt maximum (resp. minimum)
Dynamické programování
Dynamické programování prof. Ing. Pavel Tvrdík CSc. Katedra počítačových systémů Fakulta informačních technologií České vysoké učení technické v Praze c Pavel Tvrdík, 2010 Efektivní algoritmy (BI-EFA)
Parametrické programování
Parametrické programování Příklad 1 Parametrické pravé strany Firma vyrábí tři výrobky. K jejich výrobě potřebuje jednak surovinu a jednak stroje, na kterých dochází ke zpracování. Na první výrobek jsou
Prohledávání do šířky = algoritmus vlny
Prohledávání do šířky = algoritmus vlny - souběžně zkoušet všechny možné varianty pokračování výpočtu, dokud nenajdeme řešení úlohy průchod stromem všech možných cest výpočtu do šířky, po vrstvách (v každé
Úlohy krajského kola kategorie C
67. ročník matematické olympiády Úlohy krajského kola kategorie C 1. Najděte nejmenší přirozené číslo končící čtyřčíslím 2018, které je násobkem čísla 2017. 2. Pro celá čísla x, y, z platí x 2 + y z =
Obsah prezentace. Základní pojmy v teorii o grafech Úlohy a prohledávání grafů Hledání nejkratších cest
Obsah prezentace Základní pojmy v teorii o grafech Úlohy a prohledávání grafů Hledání nejkratších cest 1 Základní pojmy Vrchol grafu: {množina V} Je to styčná vazba v grafu, nazývá se též uzlem, prvkem
Časová složitost algoritmů
Časová složitost algoritmů Důležitou vlastností algoritmu je časová náročnost výpočtů provedené podle daného algoritmu Ta se nezískává měřením doby výpočtu pro různá data, ale analýzou algoritmu, jejímž
Vektorové podprostory, lineární nezávislost, báze, dimenze a souřadnice
Vektorové podprostory, lineární nezávislost, báze, dimenze a souřadnice Vektorové podprostory K množina reálných nebo komplexních čísel, U vektorový prostor nad K. Lineární kombinace vektorů u 1, u 2,...,u
Mimo samotné správnosti výsledku vypočteného zapsaným algoritmem je ještě jedno
12 Délka výpočtu algoritmu Mimo samotné správnosti výsledku vypočteného zapsaným algoritmem je ještě jedno neméně důležité hledisko k posouzení vhodnosti algoritmu k řešení zadané úlohy. Jedná se o čas,
Na začátku rozdělíme práci a určíme, které podproblémy je potřeba vyřešit. Tyto
Kapitola 1 Rozděl a panuj Rozděl a panuj je programovací metoda. Často se označuje latinsky Divide et Empera nebo anglicky Divide and Conquer. Vychází z toho, že umíme zadaný problém rozložit na menší
V předchozí kapitole jsme podstatným způsobem rozšířili naši představu o tom, co je to číslo. Nadále jsou pro nás důležité především vlastnosti
Kapitola 5 Vektorové prostory V předchozí kapitole jsme podstatným způsobem rozšířili naši představu o tom, co je to číslo. Nadále jsou pro nás důležité především vlastnosti operací sčítání a násobení
10 Přednáška ze
10 Přednáška ze 17. 12. 2003 Věta: G = (V, E) lze nakreslit jedním uzavřeným tahem G je souvislý a má všechny stupně sudé. Důkaz G je souvislý. Necht v je libovolný vrchol v G. A mějme uzavřený eurelovský
Už známe datové typy pro representaci celých čísel i typy pro representaci
Dlouhá čísla Tomáš Holan, dlouha.txt, Verse: 19. února 2006. Už známe datové typy pro representaci celých čísel i typy pro representaci desetinných čísel. Co ale dělat, když nám žádný z dostupných datových
Obsah. Euler-Fermatova věta. Reziduální aritmetika. 3. a 4. přednáška z kryptografie
Obsah Počítání modulo n a jeho časová složitost 3. a 4. přednáška z kryptografie 1 Počítání modulo n - dokončení Umocňování v Zn 2 Časová složitost výpočtů modulo n Asymptotická notace Základní aritmetické
Vzorce počítačové grafiky
Vektorové operace součet vektorů rozdíl vektorů opačný vektor násobení vektoru skalárem úhel dvou vektorů velikost vektoru a vzdálenost dvojice bodů v rovině (v prostoru analogicky) u = B A= b a b a u
Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague
1 / 40 regula Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague regula 1 2 3 4 5 regula 6 7 8 2 / 40 2 / 40 regula Iterační pro nelineární e Bud f reálná funkce
Digitální učební materiál
Digitální učební materiál Číslo projektu: CZ.1.07/1.5.00/34.0548 Název školy: Gymnázium, Trutnov, Jiráskovo náměstí 325 Název materiálu: VY_32_INOVACE_147_IVT Autor: Ing. Pavel Bezděk Tematický okruh:
NEJKRATŠÍ CESTY I. Doc. RNDr. Josef Kolář, CSc. Katedra teoretické informatiky, FIT České vysoké učení technické v Praze
NEJKRATŠÍ CESTY I Doc. RNDr. Josef Kolář, CSc. Katedra teoretické informatiky, FIT České vysoké učení technické v Praze BI-GRA, LS 2010/2011, Lekce 7 Evropský sociální fond Praha & EU: Investujeme do vaší
Úlohy klauzurní části školního kola kategorie A
6. ročník matematické olympiády Úlohy klauzurní části školního kola kategorie A. V oboru reálných čísel řešte soustavu rovnic y + 3x = 4x 3, x + 3y = 4y 3. 2. V rovině uvažujme lichoběžník ABCD se základnami
8. Geometrie vrací úder (sepsal Pavel Klavík)
8. Geometrie vrací úder (sepsal Pavel Klavík) Když s geometrickými problémy pořádně nezametete, ony vám to vrátí! Ale když užzametat,takurčitěnepodkoberecamístosmetákupoužijtepřímku.vtéto přednášce nás
Stromy. Strom: souvislý graf bez kružnic využití: počítačová grafika seznam objektů efektivní vyhledávání výpočetní stromy rozhodovací stromy
Stromy úvod Stromy Strom: souvislý graf bez kružnic využití: počítačová grafika seznam objektů efektivní vyhledávání výpočetní stromy rozhodovací stromy Neorientovaný strom Orientovaný strom Kořenový orientovaný
Stromové rozklady. Definice 1. Stromový rozklad grafu G je dvojice (T, β) taková, že T je strom,
Stromové rozklady Zdeněk Dvořák 25. října 2017 Definice 1. Stromový rozklad grafu G je dvojice (T, β) taková, že T je strom, β je funkce přiřazující každému vrcholu T podmnožinu vrcholů v G, pro každé
Implementace LL(1) překladů
Překladače, přednáška č. 6 Ústav informatiky, FPF SU Opava sarka.vavreckova@fpf.slu.cz Poslední aktualizace: 30. října 2007 Postup Programujeme syntaktickou analýzu: 1 Navrhneme vhodnou LL(1) gramatiku
Předmět: Algoritmizace praktické aplikace
Předmět: Algoritmizace praktické aplikace Vytvořil: Roman Vostrý Zadání: Vytvoření funkcí na stromech (reprezentace stromu haldou). Zadané funkce: 1. Počet vrcholů 2. Počet listů 3. Součet 4. Hloubka 5.
Sada 1 - Základy programování
S třední škola stavební Jihlava Sada 1 - Základy programování 17. Řadící algoritmy Digitální učební materiál projektu: SŠS Jihlava šablony registrační číslo projektu:cz.1.09/1.5.00/34.0284 Šablona: III/2
61. ročník matematické olympiády III. kolo kategorie A. Hradec Králové, března 2012
61. ročník matematické olympiády III. kolo kategorie Hradec Králové, 5. 8. března 01 MO 1. Najděte všechna celá čísla n, pro něž je n 4 3n + 9 prvočíslo. (leš Kobza) Řešení. Zadaný výraz lze jednoduchou
Analytická geometrie kvadratických útvarů v rovině
Analytická geometrie kvadratických útvarů v rovině V následujícím textu se budeme postupně zabývat kružnicí, elipsou, hyperbolou a parabolou, které souhrnně označujeme jako kuželosečky. Současně budeme
for (i = 0, j = 5; i < 10; i++) { // tělo cyklu }
5. Operátor čárka, - slouží k jistému určení pořadí vykonání dvou příkazů - oddělím-li čárkou dva příkazy, je jisté, že ten první bude vykonán dříve než příkaz druhý. Např.: i = 5; j = 8; - po překladu
PŘEDNÁŠKA 2 POSLOUPNOSTI
PŘEDNÁŠKA 2 POSLOUPNOSTI 2.1 Zobrazení 2 Definice 1. Uvažujme libovolné neprázdné množiny A, B. Zobrazení množiny A do množiny B je definováno jako množina F uspořádaných dvojic (x, y A B, kde ke každému
Složitost algoritmů. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava
Složitost algoritmů doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava Prezentace ke dni 27. prosince 2015 Jiří Dvorský (VŠB TUO) Složitost algoritmů
Seminář z IVT Algoritmizace. Slovanské gymnázium Olomouc Tomáš Kühr
Seminář z IVT Algoritmizace Slovanské gymnázium Olomouc Tomáš Kühr Algoritmizace - o čem to je? Zatím jsme se zabývali především tím, jak určitý postup zapsat v konkrétním programovacím jazyce (např. C#)
Základy algoritmizace c2005, 2007 Michal Krátký, Jiří Dvorský1/39
Základy algoritmizace Michal Krátký 1, Jiří Dvorský 1 1 Katedra informatiky VŠB Technická univerzita Ostrava Základy algoritmizace, 2006/2007 Základy algoritmizace c2005, 2007 Michal Krátký, Jiří Dvorský1/39
Binární vyhledávací stromy
Binární vyhledávací stromy Definice: Binární vyhledávací strom (po domácku BVS) je buďto prázdná množina nebo kořen obsahující jednu hodnotu a mající dva podstromy (levý a pravý), což jsou opět BVS, ovšem
Vrcholová barevnost grafu
Vrcholová barevnost grafu Definice: Necht G = (V, E) je obyčejný graf a k N. Zobrazení φ : V {1, 2,..., k} nazýváme k-vrcholovým obarvením grafu G. Pokud φ(u) φ(v) pro každou hranu {u, v} E, nazveme k-vrcholové
FIT ČVUT MI-LOM Lineární optimalizace a metody. Dualita. Evropský sociální fond Praha & EU: Investujeme do vaší budoucnosti
FIT ČVUT MI-LOM Lineární optimalizace a metody Dualita Evropský sociální fond Praha & EU: Investujeme do vaší budoucnosti Michal Černý, 2011 FIT ČVUT, MI-LOM, M. Černý, 2011: Dualita 2/5 Dualita Evropský
Poslední nenulová číslice faktoriálu
Poslední nenulová číslice faktoriálu Kateřina Bambušková BAM015, I206 Abstrakt V tomto článku je popsán a vyřešen problém s určením poslední nenulové číslice faktoriálu přirozeného čísla N. Celý princip
Úvod do programování 7. hodina
Úvod do programování 7. hodina RNDr. Jan Lánský, Ph.D. Katedra informatiky a matematiky Fakulta ekonomických studií Vysoká škola finanční a správní 2015 Umíme z minulé hodiny Syntax Znaky Vlastní implementace
Funkční objekty v C++.
Funkční objekty v C++. Funkční objekt je instance třídy, která má jako svou veřejnou metodu operátor (), tedy operátor pro volání funkce. V dnešním článku si ukážeme jak zobecnit funkci, jak používat funkční
Hledání v textu algoritmem Boyer Moore
Zápočtová práce z Algoritmů a Datových Struktur II (NTIN061) Hledání v textu algoritmem Boyer Moore David Pěgřímek http://davpe.net Algoritmus Boyer Moore[1] slouží k vyhledání vzoru V v zadaném textu
Náplň. v.0.03 16.02.2014. - Jednoduché příklady na práci s poli v C - Vlastnosti třídění - Způsoby (algoritmy) třídění
Náplň v.0.03 16.02.2014 - Jednoduché příklady na práci s poli v C - Vlastnosti třídění - Způsoby (algoritmy) třídění Spojení dvou samostatně setříděných polí void Spoj(double apole1[], int adelka1, double
PQ-stromy a rozpoznávání intervalových grafů v lineárním čase
-stromy a rozpoznávání intervalových grafů v lineárním čase ermutace s předepsanými intervaly Označme [n] množinu {1, 2,..., n}. Mějme permutaci π = π 1, π 2,..., π n množiny [n]. Řekneme, že množina S
5. Lokální, vázané a globální extrémy
5 Lokální, vázané a globální extrémy Studijní text Lokální extrémy 5 Lokální, vázané a globální extrémy Definice 51 Řekneme, že f : R n R má v bodě a Df: 1 lokální maximum, když Ka, δ Df tak, že x Ka,
Kapitola 1. Úvod. 1.1 Značení. 1.2 Výroky - opakování. N... přirozená čísla (1, 2, 3,...). Q... racionální čísla ( p, kde p Z a q N) R...
Kapitola 1 Úvod 1.1 Značení N... přirozená čísla (1, 2, 3,...). Z... celá čísla ( 3, 2, 1, 0, 1, 2,...). Q... racionální čísla ( p, kde p Z a q N) q R... reálná čísla C... komplexní čísla 1.2 Výroky -
Lineární algebra : Úvod a opakování
Lineární algebra : Úvod a opakování (1. přednáška) František Štampach, Karel Klouda LS 013/014 vytvořeno: 19. února 014, 13:15 1 0.1 Lineární prostory R a R 3 V této přednášce si na jednoduchém příkladu
Pascal. Katedra aplikované kybernetiky. Ing. Miroslav Vavroušek. Verze 7
Pascal Katedra aplikované kybernetiky Ing. Miroslav Vavroušek Verze 7 Proměnné Proměnná uchovává nějakou informaci potřebnou pro práci programu. Má ve svém oboru platnosti unikátní jméno. (Připadne, musí