Programmazione dinamica Ilaria Castelli castelli@dii.unisi.it Università degli Studi di Siena Dipartimento di Ingegneria dell Informazione A.A. 29/21 I. Castelli Programmazione dinamica, A.A. 29/21 1/35
Programmazione dinamica Introduzione Esempio 1. Prodotto di una sequenza di matrici Caratterizzazione della soluzione ottima Definizione ricorsiva della soluzione ottima Costruzione di una soluzione ottima Esempio 2. Problema della sottosequenza più lunga Ricerca esaustiva Caratterizzazione della soluzione ottima Definizione ricorsiva della soluzione ottima Strategia bottom-up Costruzione di una soluzione ottima I. Castelli Programmazione dinamica, A.A. 29/21 2/35
Introduzione La programmazione dinamica è solitamente usata per risolvere problemi di ottimizzazione il problema ammette diverse soluzioni ogni soluzione ha un costo vorremmo trovare una soluzione ottima cerchiamo una soluzione ottima, perché possono esistere varie soluzioni ottime La programmazione dinamica risolve un problema ricombinando le soluzioni di sottoproblemi I. Castelli Programmazione dinamica, A.A. 29/21 3/35
Programmazione dinamica VS Divide et impera 1 Divide et impera il problema originario è diviso in sottoproblemi indipendenti i sottoproblemi vengono risolti ricorsivamente si ricombinano le soluzioni dei sottoproblemi per ottenere la soluzione del problema originario strategia top-down 2 Programmazione dinamica il problema originario è diviso in sottoproblemi non indipendenti alcuni sottoproblemi condividono altri sottoproblemi: le parti condivise vengono risolte una sola volta, e messe a disposizione di tutti i sottoproblemi che ne necessitano a volte non è chiaro come il problema originario debba essere spezzato. In programmazione dinamica si calcolano le soluzioni di tutti i possibili sottoproblemi, e a partire da sottosoluzioni si ricavano nuove sottosoluzioni, fino a risolvere il problema originale. strategia bottom-up I. Castelli Programmazione dinamica, A.A. 29/21 4/35
Prodotto di una sequenza di matrici Problema: Si vuol effettuare il prodotto di una sequenza di matrici A 1, A 2,..., A n minimizzando il numero di moltiplicazioni scalari effettuate. Il costo dipende dalla parentesizzazione della sequenza. ((A 1 ((A 2 A 3 )(A 4...)))A n ) Esempio: A 1, A 2, A 2 con A 1 R 1x1, A 2 R 1x5, A 3 R 5x5 È meglio ((A 1 A 2 )A 3 ) oppure (A 1 (A 2 A 3 ))? I. Castelli Programmazione dinamica, A.A. 29/21 5/35
Costo della moltiplicazione tra matrici 1 MATRIX MULTIPLY(A, B) 2 i f columns [A]!= rows [ B] 3 then e r r o r " dimensioni non compatibili " 4 e l s e f o r i = 1 to rows [A] 5 f o r j = 1 to columns [B] 6 C [ i, j ] = 7 f o r k = 1 to columns [A] 8 C [ i, j ] = C [ i, j ] + A[ i, k ]B[ k, j ] 9 r e t u r n C Se A R pxq e B R qxr, allora C R pxr. Il costo dell algoritmo è dato dal numero di moltiplicazioni scalari effettuate: per ogni elemento della matrice C si effettuano q moltiplicazioni in totale p x q x r I. Castelli Programmazione dinamica, A.A. 29/21 6/35
Prodotto di una sottosequenza di matrici A 1, A 2, A 2 con A 1 R 1x1, A 2 R 1x5, A 3 R 5x5 1 ((A 1 A 2 )A 3 ) (A1 A 2 ) = (1 x 1 x 5) = 5. ((A 1 A 2 ) A 3 ) = (1 x 5 x 5) = 2.5 }{{} 1 x 5 7.5 moltiplicazioni 2 (A 1 (A 2 A 3 )) (A 2 A 3 ) = (1 x 5 x 5) = 25. (A 1 (A 2 A 3 )) = (1 x 1 x 5) = 5. }{{} 1 x 5 75. moltiplicazioni (!!!) La soluzione ((A 1 A 2 )A 3 ) costa molto meno! I. Castelli Programmazione dinamica, A.A. 29/21 7/35
Numero di parentesizzazioni Supponiamo che per risolvere il problema si controllino in maniera esaustiva tutte le possibili soluzioni. Il numero P (n) di possibili parentesizzazioni di una sequenza di n matrici è { 1 se n = 1 P (n) = n 1 k=1 P (k)p (n k) se n 2 P (k)p (n K) indica il prodotto di due sotto-parentesizzazioni: quella tra le prima k matrici, e quella tra le restanti n k. È stato dimostrato che dove è detta sequenza di numeri Catalani P (n) = C(n 1) C(n) = 1 ( 2n n + 1 n I. Castelli Programmazione dinamica, A.A. 29/21 8/35 )
Numero di parentesizzazioni Dimostrazione (traccia) Ci riconduciamo al problema equivalente del bilanciamento delle parentesi. Date n parentesi ( ) ( ed n parentesi ) i possibili modi di disporle in 2n 2n slot sono. n Le configurazioni sbagliate sono quelle in cui le parentesi non sono bilanciate: ())(, (()))(, ecc. Qualsiasi configurazione sbagliata può essere riscritta invertendo le parentesi a partire dal punto successivo a quello in cui si trova il primo errore. ())(= ()) ) ())()(= ()) )() Le configurazioni invertite hanno n 1 parentesi ( e n + 1 parentesi ). Per il modo in cui le abbiamo costruite, esiste una corrispondenza biunivoca tra queste configurazioni e quelle sbagliate con n ( ed n ). I. Castelli Programmazione dinamica, A.A. 29/21 9/35
Numero di parentesizzazioni Le possibili configurazioni invertite sono Le configurazioni corrette sono quindi ( ) ( ) ( ) 2n 2n 2n = n n n + 1 n n + 1 ( 2n n + 1 ( 2n n ) ) = ( 2n n 1 = 1 ( 2n n + 1 n ) ) = C(n) C(n) = 1 ( 2n n + 1 n ) = Ω(4 n /n 3/2 ) La ricerca esaustiva ha complessità esponenziale! I. Castelli Programmazione dinamica, A.A. 29/21 1/35
Programmazione dinamica Lo sviluppo di un algoritmo di programmazione dinamica prevede i seguenti passi: 1 Caratterizzazione di una soluzione ottima 2 Definizione ricorsiva di una soluzione ottima 3 Calcolo del valore di una soluzione ottima, secondo la strategia bottom-up 4 Costruzione della soluzione ottima (eventualmente) I. Castelli Programmazione dinamica, A.A. 29/21 11/35
Prodotto di una sequenza di matrici - Passo 1 Caratterizzazione della struttura di una soluzione ottima La soluzione ottima è del tipo ((A 1, A 2,..., A k ) (A }{{} k+1, A k+2,..., A n )) 1 k n }{{} pxq qxr il costo della soluzione ottima è costo(a 1, A 1,..., A k ) + costo(a k+1, A k+2,..., A n ) + pxqxr la parentesizzazione di ((A 1, A 2,..., A k ) deve essere ottima per la sequenza A1, A 2, A k la parentesizzazione di (A k+1, A k+2,..., A n ) deve essere ottima per la sequenza A k+1, A k+2,..., A n... se non lo fossero, ricombinandole non si otterrebbe la soluzione ottima! I. Castelli Programmazione dinamica, A.A. 29/21 12/35
Prodotto di una sequenza di matrici - Passo 2 Definizione ricorsiva del valore di una soluzione ottima Si definisce il valore di una soluzione ottima ricorsivamente, in termini dei valori delle soluzioni ottime dei sottoproblemi. Sottoproblema: A i, A i+1,..., A j con 1 i j n m[i, j] = costo minimo per la sottosequenza A i, A i+1,..., A j m[1, n] = costo minimo per l intera sequenza A 1,..., A n m[i, i] = Definizione ricorsiva: m[i, j] = (m[i, k] + m[k + 1, j] + p i 1 p k p j ) Ma a priori non si conosce k... Nota: la matrice A i ha dimensioni p i 1 xp i I. Castelli Programmazione dinamica, A.A. 29/21 13/35
Prodotto di una sequenza di matrici - Passo 2 Definizione ricorsiva m[i, j] = { se i = j min i k<j (m[i, k] + m[k + 1, j] + p i 1 p k p j ) se i < j Il valore di m[i, j] è ottenuto sommando i costi minimi del calcolo per le sottosequenze A 1,..., A k e A k+1,..., A n ed il costo del prodotto delle due matrici risultanti. (< A i,..., A k >)(< A k+1,... A n >) A i R p i 1xp i A k R p k 1xp k A j R p j 1xp j Definiamo s[i, j] = k per tenere traccia del valore k che costituisce una soluzione ottima per il sottoproblema A i,..., A j I. Castelli Programmazione dinamica, A.A. 29/21 14/35
Prodotto di una sequenza di matrici - Passo 3 Calcolo del valore di una soluzione ottima con strategia bottom-up Si calcolano i costi minimi per le sottosequenze lunghe 1, poi per quelle lunghe 2, e così via... m[1,n] l=n...... m[1,3] m[2,4] m[3,5]... m[n 2,n] l=3 m[1,2] m[2,3] m[3,4] m[4,5]... m[n 1,n] l=2 m[1,1]= m[2,2]= m[3,3]= m[4,4]=... m[n,n]= l=1 I. Castelli Programmazione dinamica, A.A. 29/21 15/35
Prodotto di una sequenza di matrici - Passo 3 1 MATRIX CHAIN ORDER( p ) / INPUT = <p, p1,..., pn> = d i m e n s i o n i 2 d e l l e m a t r i c i. Len ( p ) = n + 1 / 3 n = l e n g t h [ p ] 1 4 f o r i = 1 to n 5 m[ i, i ] = 6 f o r l = 2 to n / s o t t o s e q u e n z e l u n g h e da 2 a n / 7 f o r i = 1 to n l + 1 / i = i n i z i o s o t t o s e q u e n z a / 8 j = i + l 1 / j = f i n e s o t t o s e q u e n z a / 9 m[ i, j ] = i n f i n i t o f o r k = i to j 1 / c e r c o m[ i, j ] e k o t t i m i / 1 q = m[ i, k ] + m[ k+1, j ] + p [ i 1] p [ k ] p [ j ] 2 i f q < m[ i, j ] 3 then m[ i, j ] = q / a g g i o r n a m a t r i c e c o s t i / 4 s [ i, j ] = k / a g g i o r n a m a t r i c e i n d i c i k / 5 r e t u r n m and s Il costo q calcolato nella linea 11, dipende dai valori m[i, k] e m[k + 1, j], già calcolati nei passi precedenti. La complessità temporale è O(n 3 ) I. Castelli Programmazione dinamica, A.A. 29/21 16/35
Prodotto di una sequenza di matrici - Passo 3 Matrice Dimensione A 1 3 x 35 A 2 35 x 15 A 3 15 x 5 A 4 5 x 1 A 5 1 x 2 A 6 2 x 25 j = 1 j = 2 j = 3 j = 4 j = 5 15.75 1 7.875 2.625 1 2 9.375 4.375 75 3 3 3 11.875 3 7.125 3 2.5 3 1. 4 m[i,j] s[i,j] j = 6 15.125 1.5 5.375 3.5 5. 3 3 3 5 5 i = 1 i = 2 i = 3 i = 4 i = 5 i = 6 I. Castelli Programmazione dinamica, A.A. 29/21 17/35
Prodotto di una sequenza di matrici - Passo 3 Il numero dei sottoproblemi è relativamente basso: un problema per ogni possibile scelta di i e j, con 1 i j n. In totale: ( ) n }{{} n + = Θ(n 2 ) 2 prob.lunghezza }{{} prob. lunghezza > La memoria necessaria per le tabelle m ed s è Θ(n 2 ). Molto più efficiente rispetto alla ricerca esaustiva! Nota: con la programmazione dinamica risolviamo una sola volta i sottoproblemi comuni (ai livelli più bassi). Esempio: Le soluzioni (A 1 (A 2 A 3 ))((A 4 A 5 )A 6 ) e A 1 (((A 2 A 3 )(A 4 A 5 ))A 6 ) hanno in comune i sottoproblemi (A 2 A 3 ) e (A 4 A 5 ) I. Castelli Programmazione dinamica, A.A. 29/21 18/35
Prodotto di una sequenza di matrici - Passo 4 Costruzione di una soluzione ottima La procedura MAT RIX CHAIN ORDER restituisce il costo minimo per una soluzione ottima, ma non la soluzione stessa! La strategia per la costruzione di una soluzione ottima dipende dalle informazioni calcolate nelle fasi precedenti. La tabella s consente di ricostruire i passi necessari per giungere a una soluzione ottima. s[i, j] contiene il valore k ottimo per cui la parentesizzazione di < A i,..., A j > è suddivisa in < A i,..., A k > e < A k+1,..., A j > I. Castelli Programmazione dinamica, A.A. 29/21 19/35
Prodotto di una sequenza di matrici - Passo 4 A 1 A 2... A n A 1 A 2... A s[1,n] A s[1,n]+1 A s[1,n]+2... A n...... A 1... A s[1,s[1,n]] A s[1,s[1,n]]+1... A n............ I. Castelli Programmazione dinamica, A.A. 29/21 2/35
Prodotto di una sequenza di matrici - Passo 4 s[1, 6] = 3 A 1 A 2 A 3 A 4 A 5 A 6 s[1, 3] = 1 s[4, 6] = 5 A 1 A 2 A 3 A 4 A 5 A 6 s[2, 3] = 2 s[4, 5] = 4 A 1 A 2 A 3 A 4 A 5 A 6 A 2 A 3 A 4 A 5 Soluzione: I. Castelli Programmazione dinamica, A.A. 29/21 21/35
Prodotto di una sequenza di matrici - Passo 4 s[1, 6] = 3 A 1 A 2 A 3 A 4 A 5 A 6 s[1, 3] = 1 s[4, 6] = 5 A 1 A 2 A 3 A 4 A 5 A 6 s[2, 3] = 2 s[4, 5] = 4 A 1 A 2 A 3 A 4 A 5 A 6 A 2 A 3 A 4 A 5 Soluzione: (< A 1 A 2 A 3 >)(< A 4 A 5 A 6 >) I. Castelli Programmazione dinamica, A.A. 29/21 21/35
Prodotto di una sequenza di matrici - Passo 4 s[1, 6] = 3 A 1 A 2 A 3 A 4 A 5 A 6 s[1, 3] = 1 s[4, 6] = 5 A 1 A 2 A 3 A 4 A 5 A 6 s[2, 3] = 2 s[4, 5] = 4 A 1 A 2 A 3 A 4 A 5 A 6 A 2 A 3 A 4 A 5 Soluzione: ((A 1 )(< A 2 A 3 >))((< A 4 A 5 >)(A 6 )) I. Castelli Programmazione dinamica, A.A. 29/21 21/35
Prodotto di una sequenza di matrici - Passo 4 s[1, 6] = 3 A 1 A 2 A 3 A 4 A 5 A 6 s[1, 3] = 1 s[4, 6] = 5 A 1 A 2 A 3 A 4 A 5 A 6 s[2, 3] = 2 s[4, 5] = 4 A 1 A 2 A 3 A 4 A 5 A 6 A 2 A 3 A 4 A 5 Soluzione: ((A 1 )(A 2 A 3 ))((A 4 A 5 )(A 6 )) I. Castelli Programmazione dinamica, A.A. 29/21 21/35
Prodotto di una sequenza di matrici - Passo 4 1 MATRIX CHAIN MULTIPLY(A, s, i, j ) 2 i f j > i 3 then X = MATRIX CHAIN MULTIPLY(A, s, i, s [ i, j ] ) 4 Y = MATRIX CHAIN MULTIPLY(A, s, s [ i, j ]+1, j ) 5 r e t u r n MATRIX MULTIPLY(X ; Y) 6 e l s e r e t u r n A i La prima chiamata della procedura è MAT RIX CHAIN MULT IP LY (A, s, 1, n) Tornando all esempio, chiamando MAT RIX CHAIN MULT IP LY (A, s, 1, 6) si ottiene ((A 1 )(A 2 A 3 ))((A 4 A 5 )(A 6 )) I. Castelli Programmazione dinamica, A.A. 29/21 22/35
Programmazione dinamica Quali problemi di ottimizzazione si possono risolvere con la programmazione dinamica? 1 Sottostruttura ottima. La soluzione ottima del problema contiene al suo interno la soluzione ottima dei sottoproblemi. Nel problema della moltiplicazione di sequenze di matrici, una soluzione ottima per < A 1,..., A n > contiene una soluzione ottima per < A 1,..., A k > e per < A k+1,..., A n > Se esistesse una soluzione migliore per i sottoproblemi, allora la soluzione del problema originale non sarebbe ottima 2 Sottoproblemi sovrapposti. Alcuni sottoproblemi condividono altri sottoproblemi. Un algoritmo ricorsivo li risolverebbe più volte, mentre in programmazione dinamica vengono risolti una sola volta e il risultato viene riutilizzato. I risultati dei sottoproblemi vengono salvati in tabelle Si risparmia tempo Nel caso della moltiplicazione tra matrici, un algoritmo ricorsivo farebbe tutti i possibili tentativi ed effettuerebbe le stesse moltiplicazioni varie volte! I. Castelli Programmazione dinamica, A.A. 29/21 23/35
Problema della sottosequenza più lunga Problema: Date due sequenze X =< x 1, x 2,..., x m > e Y =< y 1, y 2,..., y n > si vuol trovare la più lunga sottosequenza comune a X ed Y (Longest Common Subsequence - LCS) Remark: Data una sequenza X =< x 1,..., x m > si dice che Z =< z 1,..., z k > è una sottosequenza di X se esiste una sequenza strettamente crescente di indici < i 1,..., i k > di X, tali che j = 1,..., k abbiamo x ij = z j. I. Castelli Programmazione dinamica, A.A. 29/21 24/35
Problema della sottosequenza più lunga Problema: Date due sequenze X =< x 1, x 2,..., x m > e Y =< y 1, y 2,..., y n > si vuol trovare la più lunga sottosequenza comune a X ed Y (Longest Common Subsequence - LCS) Remark: Data una sequenza X =< x 1,..., x m > si dice che Z =< z 1,..., z k > è una sottosequenza di X se esiste una sequenza strettamente crescente di indici < i 1,..., i k > di X, tali che j = 1,..., k abbiamo x ij = z j. X =< A B C B D A B > Y =< B D C A B A > I. Castelli Programmazione dinamica, A.A. 29/21 24/35
Problema della sottosequenza più lunga Problema: Date due sequenze X =< x 1, x 2,..., x m > e Y =< y 1, y 2,..., y n > si vuol trovare la più lunga sottosequenza comune a X ed Y (Longest Common Subsequence - LCS) Remark: Data una sequenza X =< x 1,..., x m > si dice che Z =< z 1,..., z k > è una sottosequenza di X se esiste una sequenza strettamente crescente di indici < i 1,..., i k > di X, tali che j = 1,..., k abbiamo x ij = z j. X =< A B C B D A B > Y =< B D C A B A > Una sottosequenza comune è < B C A > La più lunga sottosequenza comune è < B C B A > I. Castelli Programmazione dinamica, A.A. 29/21 24/35
Problema della sottosequenza più lunga - Alg. bruta forza Idea: Per ogni sottosequenza di X si controlla se è una sottosequenza anche di Y Si memorizzano le sottosequenze comuni trovate e si sceglie la più lunga Analisi della complessità: Esistono 2 m possibili sottosequenze per X ognuno degli m elementi può comparire o meno nella sottosequenza Si impiega tempo O(n) per controllare se una sottosequenza di X lo è anche di Y Il tempo necessario è O(n2 m ) I. Castelli Programmazione dinamica, A.A. 29/21 25/35
Problema della sottosequenza più lunga - Passo 1 Caratterizzazione di una soluzione ottima Teorema: Il problema LCS ha la proprietà di sottostruttura ottima Siano X =< x 1,..., x m > e Y =< y 1,..., y n > due sequenze, e sia Z =< z 1,..., z k > una LCS di X e Y. 1 Se x m = y n allora z k = x m = y n e Z k 1 è una LCS di X m 1 e Y n 1 2 Se x m y n allora se z k x m si ha che Z è una LCS di X m 1 e Y 3 Se x m y n allora se z k y n si ha che Z è una LCS di X e Y n 1 Dimostrazione 1 x m = y n = z k = x m = y n. Se così non fosse allora si potrebbe estendere Z con x m = y n! Quindi Z k 1 è una sottoseq. lunga k 1 sia di X m 1 che di Y n 1. Z k 1 è anche una LCS per X m 1 e Y n 1. Se così non fosse esisterebbe Z t con t > k 1, LCS di X m 1 e Y n 1. Allora Z potrebbe essere esteso con x m = y n formando una sottoseq. comune a X m e Y n, lunga t + 1 > k. Contraddizione! I. Castelli Programmazione dinamica, A.A. 29/21 26/35
Problema della sottosequenza più lunga - Passo 1 2 x m y n e z k x m = Z è una LCS di X m 1 e Y n Se così non fosse esisterebbe Z t con t > k, LCS di X m 1 e di Y n. Allora Z sarebbe una sottoseq. comune a X m e Y n lunga t > k. Contraddizione! 3 x m y n e z k y n = Z è una LCS di X m e Y n 1 (speculare rispetto al caso precedente) Se così non fosse esisterebbe Z t con t > k, LCS di X m e di Y n 1. Allora Z sarebbe una sottoseq. comune a X m e Y n lunga t > k. Contraddizione! I. Castelli Programmazione dinamica, A.A. 29/21 27/35
Problema della sottosequenza più lunga - Passo 2 Definizione ricorsiva di una soluzione ottima Il precedente teorema indica che, per sottosequenze generiche X i e Y j : 1 se x i = y j è necessario trovare una LCS per X i 1 e Y j 1. Aggiungendo x i = y j a tale LCS si ottiene una LCS per X i e Y j. 2 se x i y j è necessario risolvere due sottoproblemi: 1 trovare una LCS per X i 1 e Y j 2 trovare una LCS per X i e Y j 1 La più lunga delle due è una LCS per X i e Y j. Nota: vi sono sottoproblemi comuni! I. Castelli Programmazione dinamica, A.A. 29/21 28/35
Problema della sottosequenza più lunga - Passo 2 Definizione ricorsiva di una soluzione ottima Il precedente teorema indica che, per sottosequenze generiche X i e Y j : 1 se x i = y j è necessario trovare una LCS per X i 1 e Y j 1. Aggiungendo x i = y j a tale LCS si ottiene una LCS per X i e Y j. 2 se x i y j è necessario risolvere due sottoproblemi: 1 trovare una LCS per X i 1 e Y j 2 trovare una LCS per X i e Y j 1 La più lunga delle due è una LCS per X i e Y j. Nota: vi sono sottoproblemi comuni! Date due sequenze X i e Y i, sia Z k una loro LCS di lunghezza c[i, j]. Definizione ricorsiva se i = e j = c[i, j] = c[i 1, j 1] + 1 se i, j > e x i = y j max {c[i, j 1] + c[i 1, j]} se i, j > e x i y j I. Castelli Programmazione dinamica, A.A. 29/21 28/35
Problema della sottosequenza più lunga - Passo 3 Calcolo del valore di una soluzione ottima Algoritmo ricorsivo 1 RECURSIVE LCS(X, Y, i, j ) 2 i f i = or j = 3 then r e t u r n 4 i f x i = y j 5 then r e t u r n RECURSIVE LCS(X, Y, i 1, j 1) + 1 6 e l s e r e t u r n max (RECURSIVE LCS(X, Y, i 1, j ), 7 RECURSIVE LCS(X, Y, i, j 1)) Nota: nel caso x i y j le due chiamate ricorsive possono generare sottoproblemi comuni. I. Castelli Programmazione dinamica, A.A. 29/21 29/35
Problema della sottosequenza più lunga - Passo 3 Algoritmo ricorsivo m = 3, n = 4, x m y n 3,4 2,4 3,3 1,4 2,3 2,3 3,2 1,3 2,2 1,3 2,2 Caso peggiore: x i y j sempre. I. Castelli Programmazione dinamica, A.A. 29/21 3/35
Problema della sottosequenza più lunga - Passo 3 Strategia bottom-up 1 LCS LENGTH(X, Y) 2 m = l e n g h t [X] 3 n = l e n g h t [Y] 4 f o r i = 1 to m 5 c [ i, ] = 6 f o r j = 1 to n 7 c [, j ] = 8 f o r i = 1 to m 9 f o r j = 1 to n i f x i = y j 1 then c [ i, j ] = c [ i 1, j 1] + 1 2 b [ i, j ] = "up -left" 3 e l s e i f c [ i 1, j ] >= c [ i, j 1] 4 then c [ i, j ] = c [ i 1, j ] 5 b [ i, j ] = "up" 6 e l s e c [ i, j ] = c [ i, j 1] 7 b [ i, j ] = "left" 8 r e t u r n c and b I. Castelli Programmazione dinamica, A.A. 29/21 31/35
Problema della sottosequenza più lunga - Passo 3 b è una tabella m x n b[i, j] punta alla posizione della tabella c che corrisponde alla soluzione ottima del problema scelta calcolando il valore c[i, j] b serve per ricostruire una soluzione ottima trovata Esempio: X =< BDCABA >, Y =< ABCBDAB > (m = 6,n = 7) 1 i = 1, j = 1: x 1 = B y 1 = A c[, 1] = c[1, ] = = c[1, 1] =, b[1, 1] = up 2 i = 1, j = 2: x 1 = B = y 2 c[1, 2] = c[, 1] + 1 = 2, b[1, 2] = up-left 3 i = 1, j = 3: x 1 = B y 3 = C c[, 3] = c[1, 2] = 1 = c[1, 3] = c[1, 2] = 1, b[1, 3] = left 4 ecc I. Castelli Programmazione dinamica, A.A. 29/21 32/35
Problema della sottosequenza più lunga - Passo 3 Y j X 1 2 3 4 5 6 7 A B C B D A B i 1 B 2 D 3 C 4 A 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 3 2 2 3 c[i,j] b[i,j] Tempo = Θ(mn) Spazio = Θ(mn) (numero di sottoseq. per cui calcolare c[i, j] e b[i, j]) 5 B 1 2 2 3 3 3 4 6 A 1 2 2 3 3 4 4 I. Castelli Programmazione dinamica, A.A. 29/21 33/35
Problema della sottosequenza più lunga - Passo 4 Costuzione di una soluzione ottima Y i j X 1 2 3 4 5 6 7 A B C B D A B 1 B 2 D 3 C 4 A 5 B 6 A 1 1 1 1 1 1 1 1 2 1 2 2 2 2 2 1 1 2 2 3 1 2 2 2 3 3 3 1 1 2 2 2 3 4 2 3 3 4 4 c[i,j] b[i,j] Partendo da b[m, n] e andando a ritroso si ricostruisce la LCS trovata, in ordine inverso Ogni up-left corrisponde ad un elemento della LCS LCS = B D A B I. Castelli Programmazione dinamica, A.A. 29/21 34/35
Problema della sottosequenza più lunga - Passo 4 PRINT LCS( b, X, i, j ) i f i = or j = then r e t u r n i f b [ i, j ] = "up -left" then PRINT LCS( b, X, i 1, j 1) p r i n t x i e l s e i f b [ i, j ] = "up" then PRINT LCS( b, X, i 1, j ) e l s e PRINT LCS( b, X, i, j 1) Richiede tempo O(m + n): almeno uno dei due indici i e j viene decrementato ad ogni passo della ricorsione Per ricostruire la LCS si chiama P RINT LCS(b, X, lenght[x], lenght[y ]) I. Castelli Programmazione dinamica, A.A. 29/21 35/35