Programação Dinâmica Profa. Sandra de Amo Bacharelado em Ciência da Computação – UFU...
-
Upload
mario-caldas-sabala -
Category
Documents
-
view
216 -
download
0
Transcript of Programação Dinâmica Profa. Sandra de Amo Bacharelado em Ciência da Computação – UFU...
Programação Dinâmica
Profa. Sandra de AmoBacharelado em Ciência da Computação – UFU
Disciplina de Análise de Algoritmos
Um exemplo de motivação
Problema: encontrar o caminho mais curto entre dois vértices S e A em um grafo dirigido acíclico.
Algoritmo de Dijkstra resolve este problema em tempo O(|V|2) ou O((|E|+|V|) log(|V|) (dependendo do tipo de implementação da fila com prioridades)
Uma outra técnica para resolver este problema
- Grafos acíclicos dirigidos são linearizáveis
Linearização: vértices podem ser ordenados de modo que qualquer uv sempre vai da esquerda para a direita seguindo a ordem dos vértices
Por que isto ajuda na hora de encontrar o menor caminho entre dois vértices,por exemplo S para D ?
Encontrando o menor caminho, usando a linearização do grafo
A única maneira de chegar a D a partir de S, é vindo de B ou de C
dist(D) = comprimento total do menor caminho entre S e D = min{ dist(B) + 1, dist(C) + 3 }
Problemaoriginal
Subproblema Subproblema
Encontrando o menor caminho, usando a linearização do grafo
dist(D) = comprimento total do menor caminho entre S e D = min{ dist(B) + 1, dist(C) + 3 }
dist(B) = dist(A) + 6
dist(A) = min{ dist(C) + 4, dist(S) + 1}
dist(S) = 0
dist(C) = dist(S) + 2
Temos 4 subproblemas: dist(B), dist(A), dist(C) e dist(S) a resolverA ordem dos vértices dada pela linearização do grafo, induz uma ordemnos subproblemas !!
Programação dinâmica: características principais da técnica A solução de um problema P se reduz a • resolver completamente um conjunto de subproblemas P1, ..., Pn• Os subproblemas são ORDENADOS• Subproblemas são resolvidos em ordem crescente• Armazena-se as soluções obtidas na etapa k para resolver o problema da etapa
k+1.
Exemplo:
dist(D) = comprimento total do menor caminho entre S e D = min{ dist(B) + 1, dist(C) + 3 }
dist(B) = dist(A) + 6
dist(A) = min{ dist(C) + 4, dist(S) + 1}
dist(S) = 0
dist(C) = dist(S) + 2 dist(C) = 2
dist(A) = min{2+4, 0+1} = 1
dist(B) = 7
= min{7+1, 2+3} = 5
dist(D) = comprimento total do menor caminho entre S e D = min{ dist(B) + 1, dist(C) + 3 }
dist(B) = dist(A) + 6
dist(A) = min{ dist(C) + 4, dist(S) + 1}
dist(S) = 0
dist(C) = dist(S) + 2 dist(C) = 2
dist(A) = min{2+4, 0+1} = 1
dist(B) = 7
= min{7+1, 2+3} = 5
Caminho mais curto: S – C, C - D
Algoritmo para Caminho mais curto usando PD
Input: Grafo G = (V,E) acíclico, vértice inicial SOutput: Um array dist com |V| posições contendo na posição do vértice A, o
comprimento do caminho mais curto de S para A.
• Lineariza G; (O(|V| + |E|) • Para todo vértice x• dist(x) = inf• dist(S) = 0• Para cada v V – {S}, na ordem linear• Para cada aresta e = (u,v) ∈ E• Ke = dist(u) + l(u,v) % dist(u) já foi calculado, pois u vem antes
de v na ordem !!• dist(v) = min{Ke}
Análise de Complexidade
• Complexidade PD: O(|V|+|E|) + O(|V|) + O(|V| + |E|) = O(|V| + |E|)
• Dijkstra: O(|V|2) ou O((|E| + |V|).log(|V|)
• PD é melhor que Dijkstra (mas só funciona para grafos acíclicos dirigidos !)
Programação Dinâmica • Paradigma algoritmo bastante poderoso• Um problema P é reduzido a uma sequência ordenada de
subproblemas P1, P2,...,Pn = P • Resolve-se completamente cada subproblema na ordem até chegar
a P.• A solução de um problema Pk consiste em aplicar uma função
simples às soluções (já encontradas) de problemas Pi, com i<k.• Técnica de planejamento introduzida por Richard Bellman nos
anos 50.• O termo programação dinâmica era utilizado no sentido de
planejamento dinâmico !
Um outro exemplo: Subsequências crescentes mais longas Seja S uma sequência de números naturais {a1,a2,...,an}Uma subsequência é um subconjunto de S considerado em
sequência: ai1, ai2, ..., aik
Uma subsequência crescente é uma subsequência de S onde os números são pegos em ordem estritamente crescente
ai1 < ai2 < ... < aik
Exemplo : S = 5, 2, 8, 6, 3, 6, 9, 7
Subsequência crescente : 2, 3, 6, 9
Problema: Encontrar a subsequência crescente mais longa.
Como reduzir o problema a um problema de grafos
Associar a S (sequência original) um grafo dirigido acíclico:
Vértices = números da sequência S
Aresta (u,v): se u < v e u aparece antes de v na sequência S
subsequência crescente mais longa = caminho mais longo no grafo
Como usar a técnica de PD para resolver o problema ?
1. Precisamos encontrar os subproblemas
2. Ordenar os subproblemas em ordem crescente
3. Encontrar uma função que opera sobre resultados de subproblemas já resolvidos em etapas i < k, a fim de resolver o problema da etapa k
L(7) = comprimento do caminho mais longo finalizando no vértice v7 = 1 + max{L(0), L(1), L(3), L(4), L(5)}
v7v0
Solução usando PD
1. Constrói grafo reverso GR= (V,ER) 2. Para todo j =1,2,...,n3. Se Lista de adjacências (em GR ) do vértice j ≠ 4. L(j) = 1 + max{ L(i): (j,i) ER} 5. L(j) = 06. Retorna max{L(j): j = 1,...,n}
L(j) = comprimento do caminho mais longo finalizando em j = subsequência crescente mais longa finalizando em j.
Constrói Grafo reverso GR: O(|E| + |V|)
Complexidade: O(|V| + |E|) + O(n)
Varre os vértices em ordem crescente de GR e as listas de adjacências de cada vértice de GR
Varre os vértices para determinar max{L(j): j = 1,...,n
Pior caso: sequência original está ordenada em ordem crescente|E| = |V|2 Complexidade = O(|V|2)
Análise de Complexidade
Recursão versus PD
Complexidade = O(2|V|)
Pior Caso: a sequência está ordenada em ordem crescente.
ARVORE DE
RECURSÃO
Profundidade = n
Nr. de nós = O(2n)
Execuções Repetidas !!!