Programação Dinâmica 1
Programação Dinâmica
• Assim como na divisão e conquista, a programação dinâmica resolve os problemas dividindo-o em subproblemas.
• Para vários problemas (polinomiais e NP-difíceis) a solução recursiva dos subproblemas não é eficiente, pois o conjunto de subproblemas a serem resolvidos não são disjuntos e o mesmo subproblema é resolvido muitas vezes.
• No método da programação dinâmica, as soluções dos subproblemas são armazenadas em vetores ou matrizes e subproblemas ainda não resolvidos são resolvidos utilizando valores de subproblemas já resolvidos.
Programação Dinâmica
Um desenvolvimento de algoritmo de programação dinâmica pode ser dividido em quatro etapas:
• Caracterização da estrutura de uma solução ótima
•Definição recursivado valor de uma solução ótima
• Mostrar como o valorde uma solução ótima pode ser computado de forma eficiente
• Mostrar como uma solução ótima pode ser construídade forma eficiente.
Programação Dinâmica 3
Problema da Multiplicação de Várias Matrizes
• Suponha que precisamos multiplicar uma seqüência de matrizes A1, A2, A3, ..., An.
• Como a multiplicação de matrizes é uma operação associativa, podemos escolher a ordem em que as multiplicações serão feitas.
• Resulta que a ordem em que as matrizes são multiplicadas faz muita diferença no número total de operações aritméticas efetuadas e, em geral, compensa encontrar a melhor ordem de fazer as multiplicações antes de se efetuar as operações de multiplicação.
Programação Dinâmica 4
Problema da Multiplicação de Várias Matrizes
• Lembre-se que para multiplicar duas matrizes A(n x m) e B(r x s), o número de colunas de A deve ser igual ao número de linhas de B, ou seja, para que a multiplicação A.B esteja bem definida, necessariamente m=r.
• A matriz resultante da multiplicação A.B possui tamanho nxs.
• O número de operações necessárias para efetuar este produto é da ordem de n.m.s.
• Por exemplo, a multiplicação A[1000x5] . B[5x100] requer 1000x5x100 = 500.000 operações e resulta em uma matriz de dimensão 1000x100.
Programação Dinâmica 5
Problema da Multiplicação de Várias Matrizes
• Suponha que precisamos calcular o seguinte produto:
A[5x1000].B[1000x10].C[10x10].
• Temos duas opções para fazer isso:
((A.B).C) ou (A.(B.C)).
• Na primeira opção, teremos que efetuar 5.1000.10 + 5.10.10 = 50500 operações.
• Na segunda opção efetuaríamos
1000.10.10 + 5.1000.10 = 150000 operações.
Problema da Multiplicação de Várias Matrizes
• Número de formas diferentes de associar n matrizes:
P(n) = 1, se n = 1.
P(n) = , para n >= 2.
P(n) = . .
Exercício: Prove por indução que P(n) >= 2n.
−
= 1 −
1
) ( ).
(
n
k
k n P k P
Ω n
n 2 / 3
4
Programação Dinâmica 7
Problema da Multiplicação de Várias Matrizes
• A estrutura de uma solução ótima:
(A1.A2...Ak)(Ak+1....An)
• Se soubermos o índice k, onde a primeira associação deverá ser feita, então a solução ótima é formada pela solução ótima da associação de A1.A2...Ak e da solução ótima para
Ak+1....An. (por quê?)
Programação Dinâmica 8
Problema da Multiplicação de Várias Matrizes
• Definição recursivado valor de uma solução ótima Sejam as matrizes A1.A2...An com dimensões
p0x p1, p1x p2, ...., pn-1x pn.
Seja min[i,j] o número mínimo de operações necessárias para efetuar o produto das matrizes Ai, ... Aj. O valor ótimo que procuramos é min[1,n].
Então, sabendo o valor ótimo para k, temos que min[i,j] = min[i,k] + min[k+1, j] + pi-1pkpj.
Programação Dinâmica 9
Problema da Multiplicação de Várias Matrizes
Então, o valor min[i,j] pode ser calculado por:
min[i,j] = 0, se i = j e
min[i,j] = min { min[i,k] + min[k+1, j] + pi-1pkpj}, se i < j .
i<= k < j
Problema da Multiplicação de Várias Matrizes
A resolução recursiva desta equação leva um tempo exponencial.
min[i,j] = 0, se i = j e
min[i,j] = min { min[i,k] + min[k+1, j] + pi-1pkpj}, se i < j .
i<= k <= j
Tempo para recursão:
T(1) >= 1
T(n) >= 1 + , para n > 1.
Exercício: Prove por indução que T(n) >= 2n.
−
=
−
1 +
1
)) ( ) ( (
n
k
k n T k T
Programação Dinâmica 11
Problema da Multiplicação de Várias Matrizes
Computando o valor ótimo:
min[i,j] = 0, se i = j e
min[i,j] = min { min[i,k] + min[k+1, j] + pi-1pkpj}, se i < j .
i<= k <= j
• Só existem valores possíveis para min[i,j].
• Além disso, o valor de min[i,j] para i < j, só depende de valores min[i,k] e min[k+1,j] que representam intervalos de valores menores.
• Isso nos indica uma forma de resolver o problemas:
n +n 2
Programação Dinâmica 12
Problema da Multiplicação de Várias Matrizes
min[i,j] = 0, se i = j e
min[i,j] = min { min[i,k] + min[k+1, j] + pi-1pkpj}, se i < j .
i<= k <= j
j
m m
m
m m
i
0 ] 5 , 4 [ 0
] 4 , 3 [ 0
] 3 , 2 [ 0
] 5 , 1 [ ]
2 , 1 [ 0
As células mais próximas da diagonal principal, representam intervalos menores.
Preenchemos a matriz da diagonal em direção à célula m[1,n], que é a solução.
valor da melhor solução
Programação Dinâmica 13
Problema da Multiplicação de Várias Matrizes
min[i,j] = 0, se i = j e
min[i,j] = min { min[i,k] + min[k+1, j] + pi-1pkpj}, se i < j .
i <= k < j
j i
0 000 . 1 0
500 . 2 750 0
125 . 7 375 . 4 625 . 2 0
875 . 11 375 . 9 875 . 7 750 . 15 0
valor da melhor solução
Dimensões: 30x35 35x15 15x5 5x10 10x 20 =>
p0=30, p1=35, p2=15, p3=5, p4=10, p5=20
= +
+
= +
+
= +
+
= +
+
= +
+
= +
+
=
375 . 11 20 . 10 . 35 0 4375 5 . 4 . 1 ] 5 , 5 [ ] 4 , 2 [
7125 20 . 5 . 35 1000 2625 5 . 3 . 1 ] 5 , 4 [ ] 3 , 2 [
000 . 13 20 . 15 . 35 2500 0 5 . 2 . 1 ] 5 , 3 [ ] 2 , 2 [ min ] 5 , 2 [
p p p m
m
p p p m
m
p p p m
m m
Problema da Multiplicação de Várias Matrizes
Tempo para preencher a matriz = O(n4).
Construindo a solução ótima:
j i
0 4 0
3 3 0
3 3 2 0
3 3 1 1 0
Esta matriz contém o valor do k usado para calcular o valor de cada célula. A solução é ((A1.(A2.A3)(A4.A5))
Programação Dinâmica 15
Distância de Edição
Problema:Dada uma string original s[1..n] e uma outra string objetivo t[1..m], queremos saber o número mínimo de operações para transformar s em t, sendo que as operações válidas são:
1. Inserção: podemos inserir um caractere em s.
2. Remoção: podemos remover um caractere de s.
3. Substituição: podemos mudar um caractere de s.
Cada operação possui um custo, por exemplo:
Inserção = 2 Remoção = 2 Substituição = 1
O objetivo é transformar s em t com o menor custo.
Programação Dinâmica 16
Distância de Edição
s[1..i], prefixo de tamanho i de s;
t[1..j], prefixo de tamanho j de t;
dist[i,j] = custo de transformarmos s[1..i] em t[1..j].
Caracterização da solução ótima:
s
t
i
j-1 j
Se inserimos t[j] no final de s[1..i], então dist[i,j] = 2 + dist[i, j-1].
Programação Dinâmica 17
Distância de Edição
s
t
i-1 i
j
Se removermos s[i], então dist[i,j] = 2 + dist[i-1, j].
x
s
t
i-1 i
j-1 j
Substituindo s[i] por t[j], dist[i,j] = 1 + dist[i-1, j-1]
a
b
Distância de Edição
Finalmente,
s
t
i-1 i
j-1 j
Mantemos s[i], pois s[i] = t[j], dist[i,j] = dist[i-1, j-1]
a
a
Programação Dinâmica 19
Distância de Edição
s[1..i], prefixo de tamanho i de s;
t[1..j], prefixo de tamanho j de t;
dist[i,j] = custo de transformarmos s[1..i] em t[1..j].
− +
− +
≠ +
=
=
t[j]
de inserção
], 1 , [ 2
s[i]
de remoção
], , 1 [ 2
t[j]
s[i]
se 1], - j 1, - dist[i 1
t[j]
s[i]
se 1], - j 1, - dist[i min
] , [
j i dist
j i j dist
i dist
dist[i,0] = 2*i;
dist[0,j] = 2*j;
Programação Dinâmica 20
Distância de Edição
j i
8 6 4 2
8 6 4 2 0
− +
− +
≠ +
=
=
t[j]
de inserção
], 1 , [ 2
s[i]
de remoção
], , 1 [ 2
t[j]
s[i]
se 1], - j 1, - dist[i 1
t[j]
s[i]
se 1], - j 1, - dist[i min
] , [
j i dist
j i j dist
i dist
valor da solução ótima
Programação Dinâmica 21
Distância de Edição
s = apontar t = pronto
Exemplo: p r o n t o
a p o n t a r
0 2 4 6 8 10 12
2 1 3 5 7 9 11
4 2 2 4 6 8 10
6 4 3 2 4 6 8
6 5 4 2 4 6
8 10 12 14
8 7 6 4 2 6
10 9 8 6 4 3
12 10 10 8 7 5
Valor da solução ótima
Distância de Edição
s = apontar t = pronto
Transformando s em t:
apontar ppontar prontar prontor pronto
= +1
= +1
= +1
= +2 --- custo = 5
p r o n t o
a p o n t a r
0 2 4 6 8 10 12
2 1 3 5 7 9 11
4 2 2 4 6 8 10
6 4 3 2 4 6 8
6 5 4 2 4 6
8 10 12 14
8 7 6 4 2 6
10 9 8 6 4 3
12 10 10 8 7 5
outra solução ótima
Programação Dinâmica 23
Problemas Similares ao Problema da Distância de Edição
1. Alinhamento de Seqüências 1.a. Global
s = A C C T G A C T G A T A - t = T C - T G A T A G A T A A 1.b. Local
s = A T A T G C A C C T A C T A G C A A A A A C t = - - - C A C - T A T T A G - - - - 2. Subseqüência Comum de Tamanho Máximo
s = A S X SB A R R AD S O PQ R S t = S X S AARA RY I P AI PA SQ B
=> S X S A R R A P S tamanho = 9
Penalidades (exemplo):
Iguais = 2 Diferentes = -1 Buraco= -3
Programação Dinâmica 24
1.a. Alinhamento Global
s = A C C T G A C T G A T A - t = T C - T G A T A G A T A A
Penalidades (exemplo):
Iguais = 2 Diferentes = -1 Buraco= -3
Sim[i,j] = similaridade entre os prefixos s[1..i] e t[1..j].
Programação Dinâmica 25
1.a. Alinhamento Global
Penalidades (exemplo):
Iguais = 2 Diferentes = -1 Buraco= -3
Sim[i,j] = similaridade entre os prefixos s[1..i] e t[1..j].
−
−
−
−
≠
= +
=
3 ] 1 , [
3 ] , 1 [
t[j]
s[i]
se 1, - 1]
- j 1, - sim[i
t[j]
s[i]
se 2, 1]
- j 1, - sim[i max
] , [
j i sim
j i j sim
i sim
sim[i,0] = -3*i;
sim[0,j] = -3*j;
1.a. Alinhamento Global
Exemplo:
s = TACTGTA t = ACGTAT
A C G T A T
T A C T G T A
0 -3 -6 -9 -12 -15 -18 -3 -1 -4 -7 -7 -10 -13 -6 -1 -2 -5 -8 -5 -8 -9 -4 1 -1 -4 -7 -6 -7 -2 0 1 -2 -5 -12
-15 -18 -21
-10 -5 0 -1 0 -3 -13 -8 -3 2 0 2
-16 -11-6 -1 4 1 s
t
Similaridade entre as seqüências
Programação Dinâmica 27
Encontrando o Alinhamento:
T A C T G T A _ _ A C _ G T A T
A C G T A T
T A C T G T A
0 -3 -6 -9 -12 -15 -18 -3 -1 -4 -7 -7 -10 -13 -6 -1 -2 -5 -8 -5 -8 -9 -4 1 -1 -4 -7 -6 -7 -2 0 1 -2 -5 -12
-15 -18 -21
-10 -5 0 -1 0 -3 -13 -8 -3 2 0 2
-16 -11-6 -1 4 1 s
t
Similaridade entre as seqüências
1.a. Alinhamento Global
Exemplo:
s = TACTGTA t = ACGTAT
Programação Dinâmica 28
1.b. Alinhamento Local
Penalidades (exemplo):
Iguais = 2 Diferentes = -1 Buraco= -3
−
− −
−
≠
= +
=
0
3 ] 1 , [
3 ] , 1 [
t[j]
s[i]
se 1, - 1]
- j 1, - sim[i
t[j]
s[i]
se 2, 1]
- j 1, - sim[i max
] , [
j i sim
j i j sim
i sim
sim[i,0] = 0;
sim[0,j] = 0;
Programação Dinâmica 29
1.b. Alinhamento Local
Exemplo:
t = TACTGA s = ACAG
T A C T G A
A C A G
0 2 0 0 0 2
0 0 4 1 0 0
0 2 1 3 0 2
0 0 1 0 5 2
s t
0 0 0
0 0 0 0 0 0 0
0
1.b. Alinhamento Local
Exemplo:
t = TACTGA s = ACAG
Encontrando o alinhamento:
Procura-se o maior valor da última linha da matriz.
TACTGA - ACAG-
T A C T G A
A C A G
0 0 0 0 0 0 0
0 0 2 0 0 0 2
0 0 0 4 1 0 0
0 0 2 1 3 0 2
0 0 1 0 5 2
s t
0
valor da solução ótima
Programação Dinâmica 31
Problema da Mochila
Definição:
Temos um conjunto de objetosS, numerados 1,2, ..., n.
O valordo objeto i é vi , para i = 1,...,n.
O pesode cada objeto é pi, para i = 1,..., n.
Queremos encher uma mochila, cuja capacidadede peso é B, de forma a maximizaro valor dos objetos carregados.
Vamos denotar por opt(X, k)o valor de uma solução para o
problema da mochila, considerando os objetos no conjunto X e uma mochila de capacidade k.
Programação Dinâmica 32
Problema da Mochila
Estrutura da Solução Ótima:
Suponha que sabemos que o objeto i deve ser colocado na mochila na solução ótima. Então, o valor da solução ótima será:
opt(S, B) = vi + opt(S-{i}, B – pi).
Ou seja, se colocamos o objeto i na mochila, só podemos utilizar as B-piunidades da sua capacidade. Assumindo que i está na solução ótima, reduzimos o problema a encontrar uma solução ótima para os objetos S-{i}, para uma mochila de capacidade B – pi.
Se soubermos que o objeto i não está na mochila, então opt(S,B) = opt(S-{i}, B).
Programação Dinâmica 33
Problema da Mochila
Definiçaõ Recursiva do Valor da Solução Ótima:
Seja Opt(i, k) o valor da solução ótima do problema Si={1,2,...,i}
para uma mochila de capacidade k. Então,
0 se , )
, (
1.
k e 1 i se ), ,
1 (
) , 1 max (
) , (
0 , , 0 ) , 0 (
0 , , 0 ) 0 , (
<
−∞
=
>
− >
− +
= −
≤
≤
∀
=
≤
≤
∀
=
k k
i Opt
p k i Opt v
k i k Opt
i Opt
B k k
k Opt
n i i
i Opt
i i
Problema da Mochila
Encontrando o Valor da Solução Ótima:
Exemplo: |S| = 4 v = [6, 3, 5, 7] p = [2, 3, 4, 7] B=10
14 14 11 11 9 9 6 6 6 0 0 4
14 14 11 11 11 9 6 6 6 0 0 3
9 9 9 9 9 9 6 6 6 0 0 2
6 6 6 6 6 6 6 6 6 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0
10 9 8 7 6 5 4 3 2 1 B 0 S
Valor da solução ótima
Programação Dinâmica 35
Problema da Mochila
O tempo de execução deste algoritmo éΘΘ(|S|.B).ΘΘ
|S| é o número de elementos e B é o tamanho da mochila.
Seja tam(B) o tamanho necessário para representar o valor B.
Assim, tam(B) = log2B bits, e o valor B é O(2tam(B)). Portanto, o algoritmo NÃO tem tempo polinomial em função do tamanho da entrada.
Um algoritmo como este, que tem tempo limitado por um polinômio que depende de números da entrada é dito
PSEUDOPOLINOMIAL.
A propósito, o problema da mochila é NP-difícil e não deveríamos esperar encontrar um algoritmo polinomial para ele.