[Notas de algoritmo] Programación dinámica DP, descripción del algoritmo

[Notas de algoritmo] Programación dinámica DP

Programación dinámica

Creo que todo el mundo usa la recursividad de forma extensiva en la implementación del código, pero la recursividad pura, aunque la implementación es muy simple, pero sabemos que en el algoritmo, la mayoría de las veces no puede tener ambas. La recursividad es una llamada de función a sí misma, y en este momento es necesario En términos de tiempo y espacio, cada llamada de función será asignada en la pila de memoria para guardar variables temporales, guardar parámetros y direcciones de retorno. Además, la recursividad a menudo tiene pasos de cálculo repetidos. Finalmente, demasiadas llamadas pueden desbordarse fácilmente.

La programación dinámica resuelve en gran medida el problema de las llamadas repetidas. Es significativamente diferente de la estrategia de divide y vencerás (Divide y vencerás) en que los subproblemas de la programación dinámica no se superponen completamente. De hecho, la programación dinámica y los algoritmos transversales son muy similares No hay nada soberbio en la idea de ??, pero para los cálculos guardados que se han hecho, los resultados se pueden calcular rápidamente cuando se repiten llamadas, ahorrando tiempo. Vale la pena mencionar que todos los problemas que pueden resolverse utilizando algoritmos codiciosos pueden resolverse mediante programación dinámica. Muchos algoritmos específicos tienen la sombra de la programación dinámica, como el algoritmo Floyd-Warshall de ruta más corta (algoritmo Floyd-Warshall)

Definición:

Un algoritmo que define la relación entre el estado del problema y el estado dividiendo el problema, de modo que el problema se pueda resolver de manera recursiva (o dividir y conquistar) [1]

Por supuesto, esta definición no es óptima, a los subproblemas recurrentes los llamamos subproblemas superpuestos (subproblema superpuesto). Entonces su definición puede ser: dividir un problema en varios subproblemas superpuestos y luego combinar las soluciones de los pequeños problemas para obtener la solución del gran problema.

La programación dinámica se utiliza ampliamente en los campos de la informática (IA, gráficos, etc.), teoría de la información, cibernética, etc.

Paso

Los métodos de programación dinámica se utilizan generalmente para resolver problemas de optimización. Este tipo de problema puede tener muchas soluciones factibles, y cada solución tiene un valor, esperamos encontrar la solución con el valor óptimo (valor máximo u óptimo). Llamamos a esta solución la solución óptima del problema (una
solución óptima), no la solución óptima (la solución óptima), porque puede haber múltiples soluciones que alcancen el valor óptimo [2. Thomas H. Cormen, Charles E. Leiserson , Ronald L. Rivest y Clifford Stein, 2019.6, China Machine Press, 204]

1. Caracterizar las características estructurales de una solución óptima
2. Definir de forma recursiva el valor
de la solución óptima 3. Calcular el valor de la solución óptima
4. Usar la información calculada para construir una solución óptima Los
primeros tres pasos son la base para la programación dinámica para resolver el problema, si solo necesitamos el valor de la solución óptima en lugar de la solución en sí, entonces podemos ignorar el cuarto paso

Ejemplo

1. Secuencia de Fibonacci
Observe el siguiente código

double F(int n){
	return (n<=1)?1:F(n-1)+F(n-2)
}

El tiempo de ejecución se muestra en la

Figura 1

Calcule T (n) = O (2 ^ n)
Si necesitamos calcular F (44) , necesitamos calcular F (43) y F (42) , y para calcular F (43) , necesitamos calcular F ( 42) , cuando cuando el número en la función se reduce, la situación se vuelve más incontrolable.
Inserte la descripción de la imagen aquí
Figura 2

Por supuesto, no necesitamos calcular * F (10) * casi diez millones de veces, por lo que debemos resolver este problema.
Existe una estrategia tan factible:
· Para evitar el cálculo doble, almacene la cantidad de cálculo intermedio en la tabla (memorización)
· Recordamos Los valores de estos cálculos son las siguientes posibles llamadas repetidas.
En el proceso de programación dinámica para resolver el problema óptimo, la solución de arriba hacia abajo puede necesitar obtener repetidamente la solución óptima para el mismo subproblema. Aquí es también donde es significativamente diferente del algoritmo de divide y vencerás, porque los subproblemas del algoritmo de divide y vencerás son completamente diferentes, por lo que el efecto es mejor.

#define MAX 100
int d[MAX]
int F(int n){
    
    
	if(n<=2)
	{
    
    
		return 1;
	}
	else
	{
    
    
		d[n-1]=F(n-1);
		d[n-2]=F(n-2);
		d[n]=d[n-1]+d[n-2];
		return d[n]
	}
}
//也可以用循环的方式
}

2. Programación de intervalos
· El curso j comienza en s [j] y termina en f [j], y el grado de importancia es w [j]> 0;
· Cuando dos cursos no se superponen, estos dos cursos se denominan Es compatible .
Objetivo: encontrar un conjunto de cursos compatibles con el mayor peso.
Inserte la descripción de la imagen aquí
Figura 3

Pasamos de lo menos profundo a lo más profundo, y el método de mayor fuerza bruta (fuerza bruta) es, por supuesto, sacar toda la disposición de cada curso y ver qué peso es el más grande. Sin embargo, esto obviamente tiene mucho margen de mejora, por ejemplo, debe haber muchas superposiciones en la organización de estos cursos. ¿Entonces lo que hay que hacer?
Cuando los pesos son todos 1, puede usar el algoritmo codicioso para ordenar directamente según la hora de finalización y comenzar desde atrás. Sin embargo, aquí se agregan diferentes pesos, por lo que cuantos más cursos se incluyan, no necesariamente significa que se obtenga el peso final y el máximo. En
este momento, DP es útil. La idea es similar al método anterior, pero una matriz Se debe agregar p. Ayudar

p [j] = el curso más grande compatible con el curso j que es más pequeño que j
. En la siguiente figura, p [2] = 0, p [7] = 3
Inserte la descripción de la imagen aquí
Figura 4

Lo presentamos de manera más completa
Def. OPT (j) = cualquier subconjunto compatible de cursos con la mayor suma de peso, que contenga solo los cursos 1, 2, ..., j
Meta. OPT (n) = con la mayor suma de peso Los mutuamente compatibles conjunto de cursos El
caso 1.OPT (j) no contiene el curso j
. Por lo tanto, su solución es contener solo el peso máximo de los cursos 1, 2, ..., j y son compatibles entre sí.

Caso 2. OPT (j) contiene el curso j
· Suma peso w [j]
· No contiene cursos incompatibles {p [j] + 1,…, j-1}
· Debe contener 1, 2, ..., p ( j) Solución óptima

Después del análisis anterior, ¿queda muy claro? También ha aparecido la fórmula de Bellman para la programación dinámica
Inserte la descripción de la imagen aquí
Figura 5

Analicemos la complejidad (complejidad) del algoritmo.
Tenga en cuenta que en cada iteración, la peor es OPT (j-1), por lo que en el proceso de programación dinámica, se ejecuta como máximo 2n veces, que es O (n), y p [j ] La adquisición se obtiene clasificando los intervalos de curso proporcionados según la hora de finalización y contando de atrás hacia adelante. La complejidad total es O (nlogn) y la complejidad total del algoritmo es O (nlogn).

3. Ajuste de curvas multipunto
Permítanme dar otro ejemplo que creo que es más interesante. Creo que todos usarán el ajuste de curvas cuando procesen datos, que es parte de nuestro proceso de investigación, pero cuando los puntos que aparecen están organizados en diferentes el intervalo cambia mucho, no hay forma de ajustar una curva. A continuación, usamos programación dinámica para resolver este problema.
Primero, observe el problema más básico:

Mínimos cuadrados
n puntos (x1, y1), (x2, y2), ..., (xn, yn) en un plano dado. Encuentre una línea y = ax + b para ajustar.
El problema más común es usar el método de mínimos cuadrados.
Inserte la descripción de la imagen aquí
Figura 6
!] (https://img-blog.csdnimg.cn/20210110134349420.png)

Figura 7

Mínimos cuadrados segmentados
· Dados n puntos (x1, y1),…, (xn, yn), x1 <x2 <… <xn, encuentre un conjunto de curvas para minimizar el error de f (x)
Inserte la descripción de la imagen aquí
Figura 8
f (x) = E + cL
E: la suma de los errores cuadrados de cada línea recta
L: el número de líneas rectas
OPT (j) = el consumo mínimo para los puntos p1, ..., pj
eij = pi, ..., SSE de pj
luego cada vez Costo = eij + c + OPT (i-1)
finalmente obtiene la ecuación de Bellman
Inserte la descripción de la imagen aquí
Figura 9

Muestra

Todos los algoritmos necesitan los siguientes tres componentes: idea principal, prueba de corrección y análisis del tiempo de ejecución.

1. La idea principal del algoritmo. Debe transmitir correctamente la idea del algoritmo en esta sección. No es necesario que proporcione todos los detalles de la solución o el motivo correcto. Por ejemplo, en un problema de programación dinámica, debe indicarnos los subproblemas, las condiciones básicas y las fórmulas recursivas en esta parte. También puede usar un pseudocódigo para que se vea más claro

2. Prueba de la corrección del algoritmo. No importa cuál sea la entrada, debe demostrar que su algoritmo es correcto. Para bucles y algoritmos iterativos, el método habitual es buscar invariantes. Un invariante de ciclo debe seguir los siguientes tres principios:
1) Está justo antes de la primera iteración y el ciclo
2) Si está justo antes de la i-ésima iteración, entonces también debe estar justo antes de la i + 1a vez Sí
3 ) Si es
correcto después de la última iteración o bucle, entonces su salida es correcta como prueba. Este invariante debe ser descrito cuidadosamente por el sistema. Si se demuestra que la corrección es correcta en la clase, entonces no tiene para probar su corrección cada vez

3. Análisis de complejidad, generalmente análisis de complejidad temporal, marcado con O (·). Y demuestre por qué esta complejidad

Habiendo dicho tanto, démosle un ejemplo. Este ejemplo proviene de mi tarea.
Dado un conjunto de enteros no negativos de longitud N y un valor W, juzgue si hay un subconjunto en este conjunto de números, de modo que la suma de los subconjuntos es igual a W?
1. Idea central: Sea S este conjunto de números enteros no negativos de entrada, construimos una matriz bidimensional de tipo booleano dp [] [] para realizar la programación dinámica, dp [i] [j ] indica si hay i antes de incluir S El subconjunto de elementos y la suma del subconjunto es j, queremos saber dp [N-1] [W]. Inicializamos primero, cuando j = 0, dp [i] [j] = cierto, la fórmula de Bellman es la
Inserte la descripción de la imagen aquí
Figura 10

2. Corrección
Obviamente, dado que el conjunto vacío es un subconjunto de todos los conjuntos, cuando j = 0, dp [i] [j] = verdadero. Para dp [i] [j], si el elemento i-ésimo es mayor que j, entonces este subconjunto no existe en la respuesta final, dp [i] [j] = dp [i-1] [j]. De lo contrario, hay dos casos: si la respuesta no contiene el elemento i-ésimo, entonces dp [i] [j] = dp [i-1] [j]. Si la respuesta contiene el elemento i-ésimo, entonces el subconjunto y reduce, dp [i] [j] = dp [i-1] [jS [i]]. Es correcto satisfacer cualquiera de las dos condiciones anteriores d [i] [j]

3. Análisis de complejidad
Debido a que hay dos capas de bucles, una de las cuales es la longitud del conjunto y la otra es el valor W, por lo que la complejidad es θ (NW)

Oh, estoy cansado de traducir mi tarea, mostremos mi respuesta a todos.
Inserte la descripción de la imagen aquí
Figura 11

para resumir

En general, la idea de la programación dinámica es muy sencilla, es decir, guardar los valores calculados previamente, ahorrando así tiempo para cálculos repetidos. Dividido en tres pasos, defina las subpreguntas, divida la pregunta principal en subpreguntas y determine el orden de las subpreguntas pequeñas a grandes que pueden hacer que la respuesta a la subpregunta pequeña constituya la respuesta a la subpregunta más grande. pregunta. El método de análisis también es muy simple, como elegir uno de los dos, elegir uno más y agregar el nuevo parámetro blablabla (Me tomó casi seis horas escribir un blog con el que estoy bastante satisfecho. Realmente no me lo imaginaba si no fuera por unas vacaciones)

Supongo que te gusta

Origin blog.csdn.net/Cplus_ruler/article/details/112414247
Recomendado
Clasificación