Estrutura de Dados e Algoritmos
Discentes:
- George Neres
- Jean Lima
- Vitor Emanuel
Greedy Method / Método Guloso
Um algoritmo guloso é usado em problemas de otimização. O algoritmo faz a escolha ideal em cada etapa, pois tenta encontrar a maneira geral ideal de resolver todo o problema. Algoritmos gulosos são bem-sucedidos em alguns problemas, mas podem falhar na procura do caso geral ótimo.
Problema: Pendrive
Tenho n arquivos digitais no meu computador. Cada arquivo i tem ti megabytes. Quero gravar o maior número possível de arquivos num pendrive que tem capacidade para c megabytes. O problema pode ser formulado assim: encontrar o maior subconjunto X do intervalo 1 .. n que satisfaça a restrição
∑i ∈ X ti ≤ c. | (A) |
(Note que queremos maximizar │X│ e não a soma ∑i ∈ X ti.)
Supondo que os arquivos estejam ordenados em ordem crescente...
Solução: Guloso
Divide and Conquer / Divisão e Conquista
Esse método consiste no seguinte:
- A instância do problema é dividida em duas ou mais instâncias menores;
- Cada instância menor é resolvida usando o próprio algoritmo que está sendo definido;
- As soluções das instâncias menores são combinadas para produzir uma solução da instância original.
Problema: Buscar elemento numa lista
Se a lista não estiver ordenada, não há o que fazer senão percorrer a lista toda. Se a lista estiver ordenada, entretanto, é possível fazer algo bem melhor.
Problema da busca em vetor ordenado: Dado um inteiro x e um vetor inteiro crescente A[1 .. n], encontrar j tal que A[j−1] < x ≤ A[j]. Ou seja, x deve estar contido em A.
O problema faz sentido para todo n natural, até mesmo para n = 0. Toda instância do problema tem solução e toda solução j pertence ao intervalo 1 .. n+1. Se x > A[n], por exemplo, então n+1 é a resposta correta.
Solução: Busca Binária
Dynamic Programming / Programação Dinâmica
O método da programação dinâmica se aplica quando o problema tem estrutura recursiva: a solução de toda instância do problema deve conter soluções de subinstâncias da instância. O consumo de tempo do algoritmo é, em geral, proporcional ao tamanho da tabela.
Estratégias:
- Recursão: resolve subproblemas recursivamente
- Memoização: Armazena valores já calculados em uma tabela.
Propriedades da estratégia de programação dinâmica:
- Subestrutura ótima: uma solução ótima para um problema contém soluções ótimas para os subproblemas.
- Subproblemas sobrepostos: uma solução recursiva contém um pequeno número de subproblemas distintos repetidos várias vezes.
Problema: Troco com moedas
Dado um valor N, se quisermos trocar em miúdos para N centavos, e tivermos um suprimento infinito de cada uma das moedas com valor de S = {S1, S2, .., Sm}, de quantas maneiras podemos fazer o troco? A ordem das moedas não importa.
Por exemplo, para N = 4 e S = {1,2,3}, existem 4 soluções: {1,1,1,1}, {1,1,2}, {2,2}, {1, 3}. Portanto, a saída deve ser 4.
Para N = 10 e S = {2, 5, 3, 6}, existem cinco soluções: {2,2,2,2,2}, {2,2,3,3}, {2,2,6}, {2,3,5} e {5,5}. Portanto, a saída deve ser 5.
Problema de uma solução recursiva sem memoização
Problema de uma solução recursiva sem memoização
Solução com Programação Dinâmica
Referências
https://askgif.com/blog/46/introduction-to-dynamic-programming/
https://www.tutorialspoint.com/data_structures_algorithms/index.htm
https://www.ime.usp.br/~pf/analise_de_algoritmos/lectures.html
https://www.geeksforgeeks.org/dynamic-programming/
Estrutura de Dados e Algoritmos
By Vitor Emanuel
Estrutura de Dados e Algoritmos
Apresentação feita na matéria inf006 - ED & A
- 273