(Rozděl a panuj. Dynamické programování. Hladové strategie. Backtracking. Meze použitelnosti i jednotlivých technik. Příklady algoritmů postavených na jednotlivých technikách.)
Túto techniku je možné ľahko popísať týmito krokmi.
Problém 1, Maximálny a minimálny prvok
Algoritmus 1, Naivný algoritmus riešiaci problém maximálneho prvku
Max(S) 1 max ← S[1] 2 for i = 2 to n do 3 if S[i] > max then max ← S[i] fi 4 od
Procedúra Max nájde najväčší prvok, podobne sa nájde medzi ostatnými prvkami najmenší prvok. Časová zložitosť tohto algoritmu je zrejme (n - 1), pokud k tomu přidáme složitost hledání minimálního prvku (n-2) (hľadáme už len medzi n-1 prvkami) máme 2n-3.
Algoritmus 2, Rozdeľ a panuj algoritmus riešiaci problém maximálneho a minimálneho prvku
function Maxmin(x, y) **predpoklad x < y 1 if y = x + 1 then return (max(S[x], S[y]),min(S[x], S[y])) fi 2 if y = x + 2 3 then použitím 3 porovnaní utrieď S[x], S[x + 1], S[y] 4 return (max, min) 5 fi 6 if y > x + 2 then 7 (max1, min1) ← Maxmin(x, ⌊(x + y)/2⌋) 8 (max2, min2) ← Maxmin(⌊(x + y)/2⌋ + 1, y) 9 return (max(max1, max2), min(min1, min2)) 10 fi
Ľahko dokážeme, že tento algoritmus je korektný. Jeho časová zložitosť je:
Indukciou sa dá ľahko dokázať, že
Časovú zložitosť máme často určenú rekurzívne. Vtedy sa jej dôkaz často oplatí použiť tzv. Master Theorem.
Def. 1, Master Theorem
Inými typickými príkladmi použitia Rozdeľ a panuj sú algoritmy mergesort, … .
Táto technika je vhodná pre riešenie optimalizačných problémov, u ktorých dochádza k prekrývaniu podproblémov.
Problém 2, Najväčšia spoločná podpostupnosť
Označenie: pre postupnosť X = definujeme jej i-ty prefix (pre i=0,…,n) ako Nech X = a Y = sú postupnosti symbolov a nech Z = je ich NSP.
Definujme c[i,j] ako dĺžku NSP postupností Xi a Yj. Platí
Poradie výpočtu:
c[1,1],…,c[1,m]
c[2,1],…,c[2,m]
.
.
.
c[n,1],…,c[n,m]
Algoritmus 2, Výpočet optimálneho riešenia
NSP(X, Y) 1 for i = 1 to m do c[i, 0] ← 0 od 2 for j = 0 to n do c[0, j] ← 0 od 3 for i = 1 to m do 4 for j = 1 to n do 5 if Xi = Yj then 6 c[i, j] ← c[i − 1, j − 1] + 1 7 b[i, j] ← ♣ 8 else if c[i − 1, j] ≥ c[i, j − 1] then 9 c[i, j] ← c[i − 1, j] 10 b[i, j] ← ♠ 11 else 12 c[i, j] ← c[i, j − 1] 13 b[i, j] ← ♥ 14 fi fi od od 15 return c, b
Algoritmus 2, Zostavenie optimálneho riešenia
Print NSP(b, X, i, j) 1 if i = 0 ∨ j = 0 then return fi 2 if b[i, j] = ♣ then 3 Print NSP(b, X, i − 1, j − 1) 4 print xi 5 else if b[i, j] = ♠ then 6 Print NSP(b, X, i − 1, j) 7 else 8 Print NSP(b, X, i, j − 1) 9 fi fi
Ďalšími príkladmi dynamického programovanie sú algoritmy: Floydov algoritmus, Warshallov algoritmus, Konštrukcia vyváženého vyhľadávacieho stromu, … .
Táto technika však nie je použiteľná pre všetky optimalizačné problémy.
Problém 3, Problém pásky
Problém má optimálnu štruktúru, pretože ak ako prvý uložíme na pásku súbor i, ostané súbory musíme usporiadať optimálne.
Hladový algoritmus: KLO = vyber spomedzi ešte neuložených súbor najkratší a ulož ho na pásku (t.j. ulož na pásku súbory od najkratsieho po najdlhší)
Dôkaz, že je takýto algoritmus naozaj korektný je možné nájsť v slajdoch k predmetnu Návrh algoritmů II.
Medzi iné hladové algoritmy patrí Dijsktrov algoritmus, Primov a Kruskallov algoritmus pre najlacnejšie kostry, Huffmanove kódy, …
Technika prehľadávania priestoru potencionálnych riešení založená na princípe Rozdeľ a panuj.
Problém 4, Problém tyčí
Pozn. Tento problém je riešiteľný dynamickým programovaním v O(nD).
Algoritmus 3, Algoritmus riešiaci problém n-tyčí
Tyč(m, l) 1 if m = 0 then 2 if l = 0 then print A fi 3 else 4 A[m] ← 0 5 Tyč(m − 1, l) 6 7 if dm ≤ l then 8 A[m] ← 1 9 Tyč(m − 1, l − dm) 10 fi 11 fi
Pri používaní backtrackingu budeme často potrebovať preskúšať všetky permutácie. Tu je algoritmus na ich zistenie.
Algoritmus 4, Algoritmus pre získanie všetkých permutácií
procedure Permutácie(m) 1 if m = 1 then kontrola vlastností else Permutácie(m − 1) 2 for i = m − 1 downto 1 do 3 vymeň A[m] a A[i] 4 Permutácie(m − 1) 5 vymeň A[m] a A[i] 6 od fi
Ľuboš Pecho, 172463, tomorrow@mail.muni.cz, 18.6.2008
Diskuze
Caute, tak sa borim s touto otazkou, a neviem presne co je myslene pod pojmom medze pouzitelnosti jednotlivych technik. Ak mate niekto nejaky napad tak sem s tym.
Nemoze to byt napr. ze dynamicke programovanie je vhodne pouzit, ked ma problem optimalnu substrukturu, backtracking zase ako obdoba brute force s odrezavanim ciest, hladove algoritmy, ked si vies vyvodit nejake lokalne kriterium a pod?
Naval nikdy nebola moja silna stranka (double FB ), takze mozno by si mal pockat na nejake dalsie vyjadrenie…
no nieco take som si pod tym predstavoval aj ja, ale tak to imho povies uz pri tom ked vysvetlujes danu techniku. Takze ak ma niekto iny nazor, napiste ho sem pls.
Souhlasím, každý způsob navrhování algoritmu má už z toho jak ten způsob je docela rozumně určené na co jej lze využít, možná by nebylo špatné doplnit to přímo do zpracování - na co všechno se to hodí, pro ty méně chápavé (respektive více chápavé, ale unavené učením :) )
Některé meze nemusí být na první pohled zřejmé a některé meze použití mohou být například takové, že algoritmus je pro problém vhodný, ale nemusí poskytovat optimální řešení(ale lepší alg. prostě neznáme)
Pozor, v Master's Lemma bylo O(n/d), což je podle materiálů na cvičení k Návalu 2 z jara 2007 špatně. Opravil jsem to na O(n^d).
Doplnil jsem význam jednotlivých proměnných v Master's Lemma.
Master's Lemma přejmenováno na Master Theorem