AL (-) - MIEI/FEUP Programação Dinâmica (--4) Técnicas de oncepção de Algoritmos (ª parte): programação dinâmica R. Rossetti, A.P. Rocha, A. Pereira, P.B. Silva, T. Fernandes AL, MIEI, FEUP Fevereiro de Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de Programação dinâmica (dynamic programming) Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de Técnicas de oncepção de Algoritmos./rr()
AL (-) - MIEI/FEUP Programação Dinâmica (--4) Aplicabilidade e abordagem Problemas resolúveis recursivamente (solução é uma combinação de soluções de subproblemas similares) Mas em que a resolução recursiva directa duplicaria trabalho (resolução repetida do mesmo subproblema) Abordagem: º) Economizar tempo (evitar repetir trabalho), memorizando as soluções parciais dos sub-problemas (gastando memória!) º) Economizar memória, resolvendo sub-problemas por ordem que minimiza nº de soluções parciais a memorizar (bottom-up, começando pelos casos base) Termo Programação vem da Investigação Operacional, no sentido de formular restrições ao problema que tornam um método aplicável Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de Exemplo: n k, versão recursiva 4 int comb(int n, int k) { if (k == k == n) return ; else return comb(n-, k) + comb(n-, k-); } Executa n k - vezes (nº de somas a efectuar é nº de parcelas -) Executa n k vezes (nº de s / parcelas que é preciso somar ) Executa n k - vezes para calcular n k!! Pode-se melhorar muito, evitando repetição de trabalho (cálculos intermédios i j ) Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de Técnicas de oncepção de Algoritmos./rr()
AL (-) - MIEI/FEUP Programação Dinâmica (--4) n k repetição de trabalho 5 5 = 4 4 9 nós/chamadas! 8 chamadas duplicadas! Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de n k - Programação dinâmica 6 Memorização de soluções parciais: n k k= k= K= K= K=4 k=5 n= n= n= i n= j n=4 4 6 4 n=5 5 5 Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de Técnicas de oncepção de Algoritmos./rr()
AL (-) - MIEI/FEUP Programação Dinâmica (--4) Implementação Guardar apenas uma coluna, e calcular da esq. para dir. (também se podia guardar linha e calc. cima p/ baixo): static final int MAXN = 5; static int c[] = new int[maxn+]; T(n,k) = O(k(n-k)) int comb(int n, int k) { S(n,k) = O(n-k) int maxj = n - k; for (int j = ; j <= maxj; j++) c[j] = ; n-k+ vezes for (int i = ; i <= k; i++) for (int j = ; j <= maxj; j++) k(n-k) vezes c[j] += c[j-]; return c[maxj]; } Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de 7 Problema da mochila 8 Um ladrão encontra o cofre cheio de itens de vários tamanhos e valores, mas tem apenas uma mochila de capacidade limitada; qual a combinação de itens que deve levar para maximizar o valor do roubo? Tamanhos e capacidades inteiros Vamos assumir nº ilimitado de itens de cada tipo Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de Técnicas de oncepção de Algoritmos./rr(4)
AL (-) - MIEI/FEUP Programação Dinâmica (--4) Exemplo 9 Itens Tamanho 4 7 8 9 apacidade da mochila: 7 Valor 4 Nome A 5 B D E Uma solução óptima: 7 7 Outra solução óptima: 8 9 4 A D E Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de Estratégia de prog. dinâmica alcular a melhor combinação para todas as mochilas de capacidade até M (capacidade pretendida) omeçar por considerar que só se pode usar o item, depois os itens e, etc., e finalmente todos os itens de a N (N = nº de itens) álculo é eficiente em tempo e espaço se efectuado pela ordem apropriada Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de Técnicas de oncepção de Algoritmos./rr(5)
AL (-) - MIEI/FEUP Programação Dinâmica (--4) Dados Entradas: N nº de itens (com nº de cópias ilimitado de cada item) size[i] ( i N) tamanho (inteiro) do item i val[i] ( i N) valor do item i M capacidade da mochila (inteiro) Dados de trabalho, no final de cada iteração i (de a N) cost[k] ( k M) melhor valor que se consegue com mochila de capacidade k, usando apenas itens de a i best[k] ( k M) último item seleccionado p/ obter melhor valor com mochila de capac. k, usando apenas itens de a i Dados de saída: cost[m] melhor valor que se consegue c/ mochila de cap. M best[m], best[m-size[best[m]], size[best[m]], etc. itens seleccionados Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de Formulação recursiva aso base (i = ; k =,, M): cost[ k] best[ k] () () = = aso recursivo (i =,, N; k =,, M) : ( cost[ k] ( best[ k] i) i) size[ i] k ( i) val[ i] + cost[ k -size[ i]], se = ( i) ( val[ i] + cost[ k -size[ i]] > cost[ k] ( i ) cost[ k], no caso contrário i, no primeiro caso acima (usa o item i) = ( i ) best[ k], no segundo caso acima (não usa o item i) Encher o resto i ) Permite usar repetidamente o item i (senão, escrevíamos i-) Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de Técnicas de oncepção de Algoritmos./rr(6)
AL (-) - MIEI/FEUP Programação Dinâmica (--4) odificação Tempo: T(N,M) = O(NM) Espaço: S(N,M) = O(M) int[] cost = new int[m+]; // iniciado c/ s int[] best = new int[m+]; // iniciado c/ s for (int i = ; i <= N; i++ ) for (int k = size[i]; k <= M; k++) if (val[i] + cost[k-size[i]] > cost[k]) { cost[k] = val[i] + cost[k-size[i]]; best[k] = i; omo k é percorrido por ordem crescente } cost[k-size[i]] já tem o valor da iteração i // impressão de resultados (valor e itens) print(cost[m]); for (int k = M; k > ; k -= size[best[k]]) print(best[k]); Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de *Evolução dos dados de trabalho 4 i size val k 4 5 6 7 8 9 4 5 6 7 - - cost[k] best[k] 4 cost[k] 4 4 4 8 8 8 6 6 6 best[k] 4 5 cost[k] 4 5 5 8 9 4 6 7 8 best[k] 7 cost[k] 4 5 5 8 4 5 6 8 4 best[k] 4 8 cost[k] 4 5 5 8 4 5 6 8 4 best[k] 4 4 5 9 cost[k] 4 5 5 8 4 5 7 8 4 best[k] 4 5 5 4 5 Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de Técnicas de oncepção de Algoritmos./rr(7)
AL (-) - MIEI/FEUP Programação Dinâmica (--4) * Subsequência crescente mais comprida 5 Exemplo: Sequência S = (9, 5,, 8, 7,,, 6, 4) Subsequência crescente mais comprida (elem s não necessariamente contíguos): (,, 4) ou (,, 6) Formulação: s,, s n - sequência l i compr. da maior subseq. crescente de (s,, s i ) p i predecessor de s i nessa subsequência crescente l i = + max { l k < k < i s k < s i } (max{ } = ) p i = valor de k escolhido para o máx. na expr. de l i omprimento final: max(l i ) Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de * álculo para o exemplo dado 6 i 4 5 6 7 8 9 Sequência si 9 5 8 7 6 4 Tamanho li Predecessor pi - - - - 6 6 Resposta: (,, 6) Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de Técnicas de oncepção de Algoritmos./rr(8)
AL (-) - MIEI/FEUP Programação Dinâmica (--4) * Números de Fibonacci 7 Formulação recursiva: F() = F() = F(n) = F(n-) + F(n-), n > Para calcular F(n), basta memorizar os dois últimos elementos da sequência para calcular o seguinte: int Fib(int n) { int a =, b = ; // F(-), F() for (int i=; i <= n; i++) {int t = a; a = b; b += t; } return b; } Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de Referências 8 Mark Allen Weiss. Data Structures & Algorithm Analysis in Java. Addison-Wesley, 999 Steven S. Skiena. The Algorithm Design Manual. Springer 998 Robert Sedgewick. Algorithms in ++. Addison-Wesley, 99 Slides de Maria ristina Ribeiro Técnicas de oncepção de Algoritmos, AL MIEI/FEUP, Fev. de Técnicas de oncepção de Algoritmos./rr(9)