Los algoritmos de programación dinámica y codiciosos construyen una solución óptima de un subproblema basado en soluciones óptimas de subproblemas más pequeños. Sin embargo, la principal diferencia es que los algoritmos codiciosos tienen una elección local del subproblema que conducirá a una respuesta óptima. Por otro lado, la programación dinámica resolvería todos los subproblemas dependientes y luego seleccionaría uno que conduciría a una solución óptima. Ambos algoritmos requieren que una solución óptima del subproblema actual se base en soluciones óptimas de subproblemas dependientes, lo que se conoce como propiedad de subestructura óptima.
En programación dinámica, necesitamos identificar lo siguiente:
- subproblemas más pequeños y sus soluciones.
- Descripción de la solución de un subproblema basada en la solución de subproblemas más pequeños (generalmente descritos como una recurrencia).
- un ordenamiento de los subproblemas de menor a mayor para construir soluciones de todos los subproblemas.
No es fácil demostrar que un algoritmo codicioso es óptimo, sin embargo, los algoritmos codiciosos tienen una implementación mucho más simple. Por ejemplo, considere el siguiente problema específico de cambio de moneda. Tienes un conjunto de monedas de denominación: [matemáticas] {1, 2, 5, 10} [/ matemáticas]. Debes encontrar el número mínimo de monedas para construir una cantidad de dinero X. Un algoritmo codicioso natural probaría la forma de denominación de mayor a menor hasta construir el dinero. Por ejemplo, construir 29 necesitaría dos 10, uno 5, dos 2.
- ¿Usar un tipo de inserción de 50 elementos tendrá el mismo tiempo de ejecución que usar un tipo de inserción de 10 elementos 5 veces?
- ¿Qué tan difícil sería para un novato la 'Introducción a los algoritmos' de Thomas H. Cormen?
- ¿Cuál es el mejor algoritmo para un conjunto de datos con muchas características correlacionadas, débiles y ruidosas?
- Cuando aumentamos la cantidad de datos de entrenamiento en el algoritmo KNN, ¿por qué se reduce la tasa de error?
- Cómo calcular la correlación de cada fila en una matriz 2D con una matriz 1D de la misma longitud
El algoritmo codicioso anterior es óptimo para el problema dado. Sin embargo, si cambiamos el conjunto de denominaciones tenemos que [math] {1, 3, 4, 10} [/ math] el algoritmo no se vuelve óptimo. Por ejemplo, para construir 6, el algoritmo codicioso usaría un 4 y dos 1s. Una respuesta óptima requiere solo dos 3s.
Un algoritmo de programación dinámica para el mismo problema funcionaría de la siguiente manera. Un subproblema [matemática] f (i) [/ matemática] identifica el número mínimo de monedas necesarias para construir una cantidad de dinero [matemática] i [/ matemática]. Los elementos de dicho algoritmo se destacan de la siguiente manera:
- (Subproblema más pequeño) Está claro que [matemática] f (0) = 0 [/ matemática] ya que necesitamos cero monedas para construir una cantidad cero de dinero.
- (recurrencia) [matemáticas] f (i) = min_ {c <= i} {f (ic) +1} [/ matemáticas], donde c es un dominio que es menor que la cantidad de dinero i.
- (Pedido) Ordene los subproblemas según la cantidad de dinero [matemática] 0 <= 1 <= 2… <= x. [/ Matemática]
El algoritmo de programación dinámica es más lento en promedio, sin embargo, garantiza la optimización de la respuesta.
Otro ejemplo de un problema con algoritmos de programación ambiciosos y dinámicos es el problema de programación de actividades descrito en “Introducción a los algoritmos” por Cormen et. al (que compara programación dinámica y codiciosa) y en “Algorithm Design” de Kleinberg y Tardos.