La programación dinámica se usa generalmente cuando el problema se puede dividir en estados y la solución del problema en su conjunto se puede derivar de la solución a los subproblemas. En general, los problemas de DP girarán en torno a un criterio de 2 piezas. Uno será un tipo de criterio MIN / MAX y el otro será el criterio limitante (por ejemplo, encontrar un MAX de algo que es COMÚN a 2 objetos, o encontrar un número MÍNIMO de A que sume a B, etc.). En ambos casos, verá que tenemos 2 criterios que van en paralelo. Probablemente encontrarás mucha jerga en la oración anterior si eres completamente nuevo en DP, pero déjame tratar de explicar esto con un ejemplo clásico de topcoder.
Así que echemos un vistazo al ingenuo Problema de monedas en la página de algoritmos de Topcoder (enlace: Tutoriales de algoritmos). Tenemos una lista de N monedas con valores (V1, V2, V3 .. Vn) y necesitamos encontrar el número mínimo de monedas que suman S. Ahora notamos 2 cosas sobre este problema. En primer lugar, se nos pide que encontremos un MÍNIMO (criterio mínimo / máximo), y en segundo lugar se nos da una Suma (criterio limitante).
El método intuitivo para resolver este problema será exponencial (recuerde que hay 2 ^ n formas de combinar cualquier número de monedas para verificar la suma, es decir, C (n, 0) + C (n, 1) +… + C (n , n) = 2 ^ n. Con la ayuda de DP, reducimos la complejidad a polinomio / lineal con un poco de espacio extra.
- ¿Qué temas matemáticos necesito aprender antes de comenzar a aprender inducción, recursión y programación dinámica?
- Si digo los números del 1 al 100 en un orden aleatorio y omito un número, ¿cómo determinaría el número que falta solo en su cabeza?
- ¿Qué estructura de datos debo usar si estoy diseñando un algoritmo que clasifica las páginas por relevancia de acuerdo con la cantidad de veces que se ven?
- ¿Qué pasaría si le preguntas a AI si sus algoritmos son autoconsistentes?
- Cómo comenzar a aprender cómo crear algoritmos de comercio Quant en Java
Aquí hay un proceso de pensamiento paso a paso para resolver esto usando programación dinámica,
0. Sea V [i] el conjunto de monedas i.
1. Vamos a definir una matriz de estado llamada min []. Lo primero que queremos hacer es definir nuestra matriz de estado.
2. Esta es la parte clave. Definiendo su matriz de estado. min [i] es el número mínimo de monedas que suma “i”. Por lo tanto, min [S] será el número mínimo de monedas que suma a “S” (es decir, nuestra respuesta).
3. Deje que min [i] sea infinito para todo i.
4. En primer lugar, me moveré por todos los estados (es decir, Min [1] a Min [S]).
5. Para cada estado, iteraré por todas mis monedas y tomaré la decisión de incluir cada moneda o no. Esta decisión para un estado particular dependerá de un estado anterior. Por ejemplo, si el valor de mi moneda es A, entonces MIN [iA] me llevará a un estado anterior (es útil seguir definiendo MIN en su cabeza) y agregar la moneda con el valor A a Min [iA] me llevará al estado “yo”.
6. Ahora necesito verificar si la adición de esta moneda realmente redujo el valor de mi estado anterior (1 + Min [iA] <Min [i]). En caso afirmativo, actualizo el estado actual (Min [i])
7) Finalmente devolveré Min [S], que intuitivamente me dará la solución al subproblema más grande (el problema en sí).
Pseudocódigo para todo este jazz:
Inicio del algoritmo:
min [i]: infinito para todo lo que
min [0]: 0
para (i = 1 a S)
para (j = 1 a N)
A = V [j]
if (A <iY Min [iA] + 1 <Min [i])
Min [i] = Min [iA] + 1
regresar Min [S]
Fin del algoritmo.
Hay más en DP que esto, por supuesto. Leer sobre Memoization definitivamente ayudará. Aquí hay un gran enlace a los problemas de DP: Problema de práctica de programación dinámica