algorithm - Diferencia entre Dividir y Conquistar Algo y Programación Dinámica
dynamic-programming divide-and-conquer (5)
¿Cuál es la diferencia entre Divide and Conquer Algorithms
y Dynamic Programming Algorithms
? ¿Cómo son los dos términos diferentes? No entiendo la diferencia entre ellos.
Por favor, tome un ejemplo simple para explicar cualquier diferencia entre los dos y sobre qué base parecen ser similares.
La otra diferencia entre divide y vencerás y la programación dinámica podría ser:
Divide y conquistaras:
- Funciona más en los sub-problemas y, por lo tanto, tiene un mayor consumo de tiempo.
- En divide y vencerás, los sub-problemas son independientes el uno del otro.
Programación dinámica:
- Resuelve los sub-problemas solo una vez y luego los almacena en la tabla.
- En la programación dinámica, el sub-problema no es independiente.
Pienso en Divide & Conquer
como un enfoque recursivo y Dynamic Programming
como relleno de tablas.
Por ejemplo, Merge Sort
es un algoritmo Divide & Conquer
, ya que en cada paso, divide la matriz en dos mitades, recursivamente llama a Merge Sort
sobre las dos mitades y luego las fusiona.
Knapsack
es un algoritmo de Dynamic Programming
, ya que está llenando una tabla que representa las soluciones óptimas para los subproblemas de la mochila en general. Cada entrada en la tabla corresponde al valor máximo que puede llevar en una bolsa de peso con los artículos 1-j.
Supongo que ya ha leído Wikipedia y otros recursos académicos sobre esto, así que no reciclaré ninguna de esa información. También debo advertir que no soy un experto en informática de ninguna manera, pero compartiré mi granito de arena sobre mi comprensión de estos temas ...
Programación dinámica
Descompone el problema en subproblemas discretos. El algoritmo recursivo para la secuencia de Fibonacci es un ejemplo de programación dinámica, porque resuelve para fib (n) resolviendo primero para fib (n-1). Para resolver el problema original, resuelve un problema diferente .
Divide y conquistaras
Estos algoritmos normalmente resuelven piezas similares del problema y luego las reúnen al final. Mergesort es un ejemplo clásico de divide y vencerás. La principal diferencia entre este ejemplo y el ejemplo de Fibonacci es que en un mergesort, la división puede ser (teóricamente) arbitraria, y no importa cómo la segmente, todavía se está fusionando y clasificando. Se debe hacer la misma cantidad de trabajo para fusionar la matriz, sin importar cómo la divida. La resolución de fib (52) requiere más pasos que resolver para fib (2).
a veces, cuando se programa de forma recursiva, llama a la función con los mismos parámetros varias veces, lo cual es innecesario.
El famoso ejemplo de números de Fibonacci:
index: 1,2,3,4,5,6...
Fibonacci number: 1,1,2,3,5,8...
function F(n) {
if (n < 3)
return 1
else
return F(n-1) + F(n-2)
}
Corramos F (5):
F(5) = F(4) + F(3)
= {F(3)+F(2)} + {F(2)+F(1)}
= {[F(2)+F(1)]+1} + {1+1}
= 1+1+1+1+1
Así que hemos llamado: 1 veces F (4) 2 veces F (3) 3 veces F (2) 2 veces F (1)
Enfoque de programación dinámica: si llama a una función con el mismo parámetro más de una vez, guarde el resultado en una variable para acceder directamente la próxima vez. La forma iterativa:
if (n==1 || n==2)
return 1
else
f1=1, f2=1
for i=3 to n
f = f1 + f2
f1 = f2
f2 = f
Llamemos a F (5) nuevamente:
fibo1 = 1
fibo2 = 1
fibo3 = (fibo1 + fibo2) = 1 + 1 = 2
fibo4 = (fibo2 + fibo3) = 1 + 2 = 3
fibo5 = (fibo3 + fibo4) = 2 + 3 = 5
Como puede ver, cada vez que necesite la llamada múltiple, simplemente acceda a la variable correspondiente para obtener el valor en lugar de volver a calcularlo.
Por cierto, la programación dinámica no significa convertir un código recursivo en un código iterativo. También puede guardar los subresultados en una variable si desea un código recursivo. En este caso, la técnica se llama memorización. Para nuestro ejemplo, se ve así:
// declare and initialize a dictionary
var dict = new Dictionary<int,int>();
for i=1 to n
dict[i] = -1
function F(n) {
if (n < 3)
return 1
else
{
if (dict[n] == -1)
dict[n] = F(n-1) + F(n-2)
return dict[n]
}
}
Entonces, la relación con Divide and Conquer es que los algoritmos de D & D se basan en la recursión. Y algunas versiones de ellos tienen esta "llamada de función múltiple con el mismo problema de parámetro". Busque "multiplicación de cadenas de matrices" y "subsecuencias comunes más largas" para ejemplos tales donde se necesita DP para mejorar el T (n) de algo de D & D.
Divide y conquistaras
Dividir y vencer funciona dividiendo el problema en subproblemas, conquista cada sub-problema recursivamente y combina estas soluciones.
Programación dinámica
La Programación Dinámica es una técnica para resolver problemas con subproblemas superpuestos. Cada sub-problema se resuelve solo una vez y el resultado de cada sub-problema se almacena en una tabla (generalmente implementada como una matriz o una tabla hash) para futuras referencias. Estas soluciones secundarias se pueden usar para obtener la solución original y la técnica de almacenamiento de soluciones de sub-problema se conoce como memorización.
Puede pensar en DP = recursion + re-use
Un ejemplo clásico para entender la diferencia sería ver ambos enfoques para obtener el n ° número de fibonacci. Verifique este material de MIT.
EDITAR
Enfoque Divide y Vence
Enfoque de programación dinámica