/ / zné algoritmy mají r znou složitost Dynamické programování / / Definice funkce Otázka Program f(x,y) = (x = ) (y = ) f(x, y-) + f(x-,y) (x > ) && (y > ) f(,) =? int f(int x, int y) { if ( (x == ) (y == )) return ; return (* f(x, y-) + f(x-,y)); Jednoduchá analýza int count = ; public static int f(int x, int y) { count++; if ( (x == ) (y == )) return ; return (* f(x, y-) + f(x-,y)); xyz = f(,); print(count); Odpov print( f(,) ); f(,) = 7 7 7 Výsledek analýzy count = 69 / 6 / Detailn jší analýza strom rekurzivního volání f(,) f(,9) f(9,) Detailn jší analýza pokra uje efektivita rekurzivního volání po et: volání hodnot f(,) f(9,) f(,8) f(9,9) f(9,9) f(8,) f(9,9) f(9,9) f(8,) f(,7) f(7,) f(7,) 8 f(,6) 9,7 9,7 8,8 9,7 8,8 8,8 7,9 9,7 8,8 8,8 7,9 8,8 7,9 7,9 f(6,) 9,7 8,8 8,8 7,9 9,7 8,8 8,8 7,9 8,8 7,9 7,9 f(6,) 6
7/ 8 / f(x,y) = (x = ) (y = ) f(x, y-) + f(x-,y) (x > ) && (y > ) f(x,y) = (x = ) (y = ) f(x, y-) + f(x-,y) (x > ) && (y > ) 9 x f(,) f(,) f(,) f(,) f(,) f(,) f(,) f(x,y-) f(x-,y) f(x,y) f(,8) 9 f(9,9) f(,9) f(,) f(8,) f(9,) f(,) y 9 y 9 7 9 7 7 9 f(x,y-) f(x-,y) f(x,y) 88 6879 9789 87 6667 777 x 9/ / static int dynarr [N+][N+]; void filldynarr() { int xy, x, y; for (xy = ; xy <= N; xy++) dynarr[][xy] = dynarr[xy][] = ; Všechny hodnoty se p edpo ítají for (y = ; y <=N; y++) for (x = ; x <= N; x++) dynarr[y][x] = *dynarr[y-][x] + dynarr[y][x-]; Volání funkce int f(int x,int y) { return dynarr[y][x]; Dynamické programování Optimální binární vyhledávací strom / / Optimální binární vyhledávací strom Optimální binární vyhledávací strom Vyvážený, ale ne optimální Cena jednotlivých uzl v BVS.8...... Klí...6..9 Pravd podobnost dotazu....... hloubka cena uzlu = pr m rný po et test na nalezení uzlu p i jednom dotazu (Find) cena uzlu = pravd podobnost hloubka. =.. =.. =.. =.88
/ / Cena vyváženého stromu Optimální BVS klí pravd p. p k hloubka d k p k d k..8.......6...9. =..8 =.. =.8. =.. =.6. =.. =.88. =..6 =.. =.. =.6.9 =.8.... =.8. =.9. =. Cena celkem:.7 Cena celkem = pr m. po. test na jednu operaci Find. Struktura optimálního BVS s danými pravd podobnostmi.8.......6....9... / 6 / Cena optimálního BVS Výpo et ceny optimálního BVS klí pravd p. p k hloubka d k p k d k..8.......6...9. =..8 =.. =.. =.. =.6. =.. =.. =.6.6 =.8. =.. =..9 =.7.... =.. =.. =. Cena celkem.6 Zrychlení.7 :.6 = :.7 C k L k- k ekurzivní myšlenka p k Xyz C k k+ C k C k cena levého podstromu uzlu k Cena pravého podstromu uzlu k p k k- Cena = C k + p i + C k + p i + p k i=k+ 7 / 8 / Malé optimální podstromy Výpo et ceny optimálního BVS Idea rekurzivního ešení: Minimalizace ceny BVS. P edpoklad : Všechny menší optimální stromy jsou známy. L N Nad prvky s indexy od L do lze jist vytvo it jeden optimální podstrom.. Zkus: k = L, L+, L+,..., k=l k=l+ k=l+... k= Velikost stromu = po. uzl = -L+ Celkem máme Máme N optimalních podstrom velikosti N- N- podstrom N N * (N+) / r zných optimálních podstrom.. Zaregistruj index k, který minimalizuje cenu, tj. zaregistruj hodnotu: k- C k + p i + C k + p i + p k i=k+. Klí s indexem k je ko enem optimálního stromu.
9 / / Minimalizace ceny BVS Datové struktury pro výpo et optimálního BVS C(L,)... Cena optimálního podstromu obsahujícího klí e s indexy L, L+, L+,..., -, k- C(L,) = min { C(L, k-) + p i + C(k+,) + p i + p k = L k i=k+ (*) = = min { C(L, k-) + C(k+,) + p i = L k min { C(L, k-) + C(k+,) + p i L k Hodnota k minimalizující (*) je indexem ko enu optim. podstromu. Ceny optimálních podstrom pole C [L][] (L ) N L L N+ diagonála... L= Ko eny optimálních podstrom pole roots [L][] (L ) L L N+ diagonála... L= / / Cena konkrétního optimálního podstromu p p p a b c d e p x p y p 6 z p7 t p 8 w p9 (nuly na diagonále a pod ní ) L k p N L=, =9 C(L,) = min { C(L, k-) + C(k+,) + p i C(L,) = min{ +x, p +y, a+z, b+t, c+w, d+p 9, e+ + p i Strategie dynamického programování nejprve se zpracují nejmenší podstromy, pak v tší, atd Stop / / Výpo et polí cen a ko en void optimaltree() { int L,, k, size; double min; // size = for (int i=; i<=n; i++) { C[i][i] = pravd podobnost[i]; [i][i] = i; // size > for (size = ; size <= N; size++) { L = ; = size; while ( <= N) { C[L][] = min(c[l][k-]+c[k+][], k = L..); roots[l][] = k minimalizující p edch. ádek ; C[L][] += sum(c[i][i], i = L..); L++; ++; Vybudování optimálního stromu pomocí pole ko en void buildtree(int L, int ) { int key; if ( < L) return; key = roots[l][]; insert(root, key); // standard BST insert buildtree( L, key-); buildtree( key+, ); Volání funkce buildtree vybuduje optimální strom: buildtree(,n);
/ 6 / Ko eny optimálních podstrom Korespondence strom 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 6 7 7 7 7 7 7 7 7 7 6 7 7 7 7 7 7 7 7 7 6 7 7 7 7 7 7 7 7 7 7 7 7 8 9 9 9 9.8.......6....9... 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 6 7 7 7 7 7 7 7 7 7 6 7 7 7 7 7 7 7 7 7 6 7 7 7 7 7 7 7 7 7 7 7 7 8 9 9 9 9 7 / 8 / Ceny optimálních podstrom -A -B -C -D -E 6-F 7-G 8-H 9-I -J -K -L -M -N -O -A...7.9.8.6.7.6..7..9.7..6 -B.8.8..9..6....9.7..9. -C....8.8.9.6..66.9... -D..6.6.8.6.7.87..9.67.8.86 -E.....68.8.8..6.77.8 6-F....6.7.6...6.67 7-G...6.6.6..7.8. 8-H.....7.78.89.9 9-I.6.6..6.66.77.8 -J....9.6.6 -K...9.. -L.9... -M..7.9 -N.. -O. Dynamické programování Nejdelší spole ná podposloupnost 9 / / Dv posloupnosti A: B: A = 8 B = 7 A n : (a, a,..., a n ) B m : (b, b,..., b m ) C k : (c, c,..., c k ) A 8 : B 7 : 6 7 8 C k = LCS(A n, B m ) C : E D D A Spole ná podposloupnost A: B: ekurzivní pravidla: C: C D A C = ( a n = b m ) ==> (c k = a n = b m ) & (C k- = LCS (A n-, B m- ) ) 6 7 8 6 7 8 Nejdelší spole ná podposloupnost (NSP) A: B: C: E D D A C = A 8 : B 7 : C : E D D A A 7 : B 6 : C : E D D A
/ / ( a n!= b m ) & (c k!= a n ) ==> (C k = LCS (A n-, B m ) ) ekurzivní funkce délka NSP A 7 : B 6 : 6 7 8 C B E A D D E D E C D B D A 6 : B 6 : 6 7 8 C B E A D D E D E C D B D C(n,m) = C(n-, m-) + max{ C(n-, m), C(n, m-) n = or m = n >, m >, a n =b m n >, m >, a n b m C : E D D C : E D D Strategie dynamického programování A : B : ( a n!= b m ) & (c k!= b m ) ==> (C k = LCS (A n, B m- ) ) 6 7 8 C B E A D D E C D B A : B : 6 7 8 C B E A D D E C D B C[n][m] m for (a=; a<=n; a++) for (b=; b<=m; b++) C[a][b] =... ; C : E D C : E D n / / Konstrukce pole pro NSP void findlcs() { int a, b; for (a=; a<=n; a++) for (b=; b <= m; b++) if (A[a] == B[b]) { C[a][b] = C[a-][b-]+; arrows[a][b] = DIAG; else if (C[a-][b] > C[a][b-]) { C[a][b] = C[a-][b]; arrows[a][b] = UP; else { C[a][b] = C[a][b-]; arrows[a][b] = LEFT; Pole NSP pro CBEADDEA a DECDBDA C A: 6 7 8 C B E A D D E A 6 7 B: / / Výpis NSP -- rekurzivn :) void outlcs(int a, int b) { if ((a == ) (b == )) return; if (arrows[a][b] == DIAG) { outlcs(a-, b-); // recursion... print(a[a]); //... reverses the sequence! else if (arrows[a][b] == UP) outlcs(a-,b); else outlcs(a,b-); zné algoritmy mají r znou složitost