-
Je použitelné na problémy, které lze rozdělit na podproblémy.
-
Obzvlášť vhodné je pak v těch případech, kde se podproblémy překrývají — dochází k tomu, že se něco počítá víckrát.
Algoritmy a datové struktury

Note
|
Pokročilé techniky návrhu algoritmů: dynamické programování, hladové strategie, backtracking. Amortizovaná analýza. IV003 |
Pokročilé techniky návrhu algoritmů
Dynamické programování
I thought dynamic programming was a good name. It was something not even a Congressman could object to. So I used it as an umbrella for my activities.
Eye of the Hurricane: An Autobiography (1984
Intutivně je dynamické programování spojením dvou věcí: "rozbalené" rekurze (taky se tomu říká bottom-up přístup) a memoizace.
Konkrétněji, dynamické programování je vhodnou technikou, pokud:
-
podproblémů je polynomiální počet,
-
(optimální) řešení původního problému lze jednoduše spočítat z (optimálních) řešení jeho podproblémů,
-
podproblémy jde přirozeně seřadit od nejmenšího po největší.
Tip
|
O tom, že problémů musí být polynomiální počet, přemýšlím intuitivně tak, že se musí dát vyřešit v nějakém vícenásobném Pokud mám zanořených cyklů, vyřeším nejvíc podproblémů. |
Memoizace
Memoizace v zásadě není nic jiného než tabulka, pole, HashSet
, nebo něco podobného, kam si algoritmus ukládá řešení jednotlivých podproblémů.
Tip
|
V pseudokódu se označuje jako (asi memory), (asi array), nebo (asi cache). |
Bottom-up
Rekurze tradičně řeší problém zeshora — začně celým problémem, který si rozdělí na podproblémy, a ty na podpodproblémy, atd. Bottom-up approach jde na to obráceně. Začně těmi nejmenšími podproblémy a postupně se prokousává k rešení celku.
Jediným háček je v tom přijít na to, které podproblémy jsou ty nejmenší a v jakém pořádí je musíme spočítat, aby byly všechny připravené pro výpočet větších podproblémů. Bez tohohle algoritmus nebude fungovat korektně.
Note
|
Zjednodušeně jde o to přetransformovat rekurzi na cykly. Pěkný vedlejším efektem je, že je jednodušší určit složitost algoritmu. |
Kuchařka
-
Rozděl problém na (překrývající se) podproblémy.
-
Napiš rekurzivní algoritmus nebo alespoň Bellmanův rekurentní vztah (značený protože dává optimální řešení).
-
Urči správné pořadí počítání podproblémů tak, aby se každý počítal právě jednou (bottom-up přístup).
-
Pokud je to nutné, sestav z optimální hodnoty její realizaci (třeba cestu nebo něco).
-
Sepiš pseudokód.
-
Dokaž korektnost rekurentního vztahu, bottom-up pořadí a rekonstrukce (zejména terminace).
-
Okomentuj složitost.
Problémy
- Weighted interval scheduling
-
Z množiny intervalů (událostí, úkolů, atd.), které se mohou překrývat v čase, a mají určitou váhu , vyber takovou množinu intervalů , pro kterou je maximální.
- Řešení
-
Řešení využívá toho, že čas plyne výhradně dopředu, takže se můžeme na podproblémy dívat chronologicky a nebudou se překrývat.
Nechť je index takové události , že a jsou kompatibilní.
- Parenthesization
-
Mějme hromadu matic, které chceme pronásobit. Víme, že maticové násobení je asociativní, takže můžeme zvolit různé pořadí násobení — různé odzávorkování. Nicméně, není komutativní, takže nesmíme matice prohazovat. Cena násobení matice o velikosti a je . Jaké pořadí zvolit, aby byl výsledný součin co nejlevnější?
- Problém
-
Máme matice , které chceme pronásobit.
Potřebujeme najít index takový, že je nefektivnější. To nám problém rozděluje na dva podproblémy: červený a modrý.
- Řešení
-
- Knapsack
-
Mějme batoh s nosností a věcí, které bychom do něj rádi naložili. Každá věc má hodnotu a váhu . Jaké věci vybrat, aby byla hodnota naložených věcí co největší, ale batoh je furt unesl?
- Řešení
-
Vychází z myšlenky, že batoh, ve kterém už něco je, je jakoby batoh s nižší nosností.
Procházíme věci postupně přes index a pro každou řešíme, jestli ji chceme v batohu o nosnosti :
Hladové (greedy) strategie
Přijde Honza na pracovní pohovor a budoucí šéf se ho ptá: "Co je vaše dobrá schopnost?" Honza odpoví: "Umím rychle počítat." "Kolik je 1024 na druhou?" "MILION STO TISÍC," vyhrkne ze sebe Honza. Šéf se chvíli zamyslí a povídá: "Ale to je špatně, výsledek je 1048576!" A Honza na to: "No sice špatně, ale sakra rychle!"
Greedy algoritmy nachází řešení globálního problému tak, že volí lokálně optimální řešení. Tahle taktika nemusí vést ke globálně optimálnímu řešení, ale alespoň ho spočítá rychle.
-
Ve výpočtu směřuje bottom-up.
-
Ideálně funguje na problémy, kde optimální řešení podproblému je součástí optimálního řešení celého problému.
-
Dobře se navrhuje, špatně dokazuje.
Problémy
- Cashier’s algorithm (mince)
-
Jak zaplatit danou částku s co nejmenším počtem mincí různých hodnot?
- Řešení
-
V každé iteraci vol minci s nejvyšší hodnotou, dokud není zaplacena celá částka.
- Interval scheduling
-
Z množiny intervalů, které mají začátek a konec, ale mají stejnou hodnotu, vyber největší podmnožinu intervalů, které se nepřekrývají.
- Řešení
-
Vybereme ty, které končí nejdřív.
Backtracking
Inteligentní brute-force nad prostorem řešení.
Technika hledání řešení problému postupným sestavováním kandidátního řešení. [5]
-
Částečný kandidát může být zavrhnut, pokud nemůže být dokončen.
-
Můžeme dokonce zavrhnout kompletní řešení, pokud je chceme najít všechna.
-
Pokud je kandidát zavrhnut, algoritmus se vrátí o kus zpět (backtrackuje), upraví parametry a zkusí to znovu.
Dynamické programování | Backtracking |
---|---|
Hledá řešení překrývajících se podproblémů. |
Hledá všechna řešení. |
Hledá optimální řešení. |
Hledá všechna, libovolná řešení, hrubou silou. |
Má blíž k BFS — staví "vrstvy". |
Má blíž k DFS — zanoří se do jednoho řešení a pak se vrátí. |
Typicky zabírá víc paměti kvůli memoizaci. |
Typicky trvá déle, protože hledá všechna řešení. |
Mívá cykly. |
Mívá rekurzi. |
Problémy
- Sudoku
-
Hledá řešení tak, že pro pole vybere možné řešení a zanoří se, pokud funguje tak hurá, pokud ne, tak backtrackuje a zkusí jinou možnou cifru.
- Eight queens
-
Jak rozestavit osm šachových královen na šachovnic tak, aby se vzájemně neohrožovaly?
Amortizovaná analýza
- amortize(v)
amortisen — "to alienate lands", "to deaden, destroy"
amortir (Old French) — "deaden, kill, destroy; give up by right"
*admortire (Vulgar Latin) — to extinquish
Umožňuje přesnější analýzu časové a prostorové složitosti, protože uvažujeme kontext, ve které se analyzovaný algoritmus používá. Určujeme složitost operace v posloupnosti operací, ne samostatně.
Tip
|
Viz bakalářská otázka Korektnost a složitost algoritmu. |
Základními pojmy analýzy složitosti jsou:
- Časová složitost
-
Funkce velikosti vstupu algoritmu. Počítá počet kroků (nějaké výpočetní jednotky) potřebných k vyřešení problému.
- Prostorová složitost
-
Funkce velikosti vstup algoritmu. Počítá počet polí (nějaké jednotky prostoru), která algoritmus potřebuje navštívit k vyřešení problému.
- Asymptotická notace
-
Umožňuje zanedbat hardwarové rozdíly. Popisuje, že složitost roste alespoň tak, nejvýš tak nebo stejně jako jiná funkce.
- Big O
-
Horní mez, složitost v nejhorším případě. Množina funkcí rostoucích stejně rychle jako , nebo pomaleji:
- Omega
-
Spodní mez, složitost v nejlepším případě. Množina funkcí rostoucích stejně rychle jako , nebo rychleji.
- Theta
-
Horní i spodní mez. Množina funkcí rostoucích stejně rychle jako .
Aggregate method (brute force)
Analyzujeme celou sekvenci operací najednou. Nepoužíváme žádné chytristiky ani fígle.
- Věta
-
Pokud začneme s prázdným zásobníkem, pak libovolná posloupnost operací
Push
,Pop
aMulti-Pop
zabere času. - Důkaz
-
-
Každý prvek je
Pop
nut nejvýše jednou pro každý jehoPush
. -
V posloupnosti je
Push
ů. -
V posloupnosti je
Pop
ů (včetně těch vMulti-Pop
u). -
Celá posloupnost má tak nejvýše složitost .
-
Accounting method (banker’s method)
Používá fígl, kdy velké množství levných operací "předplatí" jednu drahou operaci. Využívá metaforu bankovního účtu.
-
Každé operaci přiřadíme fiktivní kreditovou cenu.
-
Při realizaci operace zaplatíme skutečnou cenu naspořenými kredity.
-
Počáteční stav je 0 kreditů.
Pro každou operaci v posloupnosti:
-
Pokud je skutečná cena nižší než kreditová, tak zaplatíme skutečnou cenu a přebývající kredity uspoříme na účtu.
-
Pokud je skutečná cena vyšší než kreditová, tak zaplatíme skutečnou cenu a případný nedostatek kreditů doplatíme z úspor na účtu.
Important
|
Pokud je po celou dobu provádění operací stav účtu nezáporný, pak je skutečná složitost celé posloupnosti operací menší nebo rovna součtu kreditových cen operací. |
Warning
|
Pokud stav účtu kdykoliv během posloupnosti klesne pod nulu, pak jsou kreditové ceny nastaveny špatně! |
Tip
|
Tato metoda se dá upravit tak, že kredity náleží individuálním objektům ve struktuře místo struktury jako celku. Cena operace se pak platí z kreditů objektů, nad kterým operace probíhá. |
Operace | Skutečná cena | Kreditová cena |
---|---|---|
|
1 |
2 |
|
1 |
0 |
|
0 |
- Invariant
-
Počet kreditů na účtu je rovný počtu prvků na zásobníku.
- Důkaz
-
-
Invariant platí pro prádný zásobník.
-
S
Push
operací se na účet připíše právě 1 kredit. (Čímž se předplatíPop
neboMulti-Pop
.) -
Pop
aMulti-Pop
operace spotřebují právě 1 kredit z účtu. -
Tedy stav účtu nikdy neklesne pod 0.
-
Tedy složitost posloupnosti je nejvýše součet kreditových cen, tedy .
-
Potential method (physicist’s method)
Hraje si s představou toho, že struktura je fyzikální systém s nějakou energetickou hladinou — potenciálem. Výhodou této metody je, že stačí zvolit jednu funkci, která splňuje dané podmínky. Nevýhodou je, že takovou funkci najít je těžké. Člověk zkrátka buď dostane nápad nebo ne.
- Potenciálová funkce
-
Funkce , která přiřadí dané struktuře hodnotu. Platí, že:
- Amortizovaná cena
-
Pokud je skutečná cena operace, pak pro amortizovanou cenu platí:
- Potenciálová věta
-
Počínaje počátečním stavem , celková skutečná cena posloupnosti operací je nejvýše součet jejich amortizovaných cen.
- Důkaz
-
(počet prvků na zásobníku)
Operace | Skutečná cena | Amortizovaná cena |
---|---|---|
|
1 |
|
|
1 |
|
|
- Věta
-
Počínaje prázdným zásobníkem, libovolná sekvence operací zabere času.
- Důkaz (případ
Push
) -
-
Skutečná cena je .
-
Amortizovaná cena je .
-
- Důkaz (případ
Pop
) -
-
Skutečná cena je .
-
Amortizovaná cena je .
-
- Důkaz (případ
Multi-Pop
) -
-
Skutečná cena je .
-
Amortizovaná cena je .
-
- Důkaz (závěr)
-
-
Amortizovaná cena všech operací je .
-
Součet amortizovaných cen posloupnosti operací je pak .
-
Z potenciálnové věty plyne, že skutečná cena posloupnosti je .
-