¿Cuál es la optimización de Knuth en la programación dinámica?

La optimización de Knuth en programación dinámica se aplica específicamente para problemas óptimos de árbol binario. (Lea sobre los árboles de búsqueda binarios óptimos en la sección del árbol de búsqueda binaria del volumen 3 “El arte de la programación de computadoras” de Knuth para más detalles)

Es aplicable en el caso donde la recurrencia es en la forma:
dp [ i ] [ j ] = mini < k < j { dp [ i ] [ k ] + dp [ k ] [ j ]} + C [ i ] [ j ]

La condición suficiente para la aplicabilidad es:
A [ i , j – 1] ≤ A [ i , j ] ≤ A [ i + 1, j ]

Dónde,

  • A [ i ] [ j ]: la k más pequeña que da una respuesta óptima, por ejemplo en:
  • dp [ i ] [ j ] = dp [ i – 1] [ k ] + C [ k ] [ j ]
  • C [ i ] [ j ] – función de costo dada
  • Además, es importante tener en cuenta que Knuth Optimization es aplicable si: C [ i ] [ j ] cumple las siguientes 2 condiciones:
  • desigualdad cuadrangular :
  • monotonicidad :

No sabía sobre la condición de desigualdad del cuadrilátero hasta que lo leí @ Optimizaciones de programación dinámica – Codeforces

La aplicación de esta optimización reduce la complejidad del tiempo de O (n ^ 3) a O (n ^ 2) y es útil para resolver un grupo particular de problemas, como:

Problemas :: Mostrar problema

La optimización de Knuths funciona para la optimización en subcadenas para las cuales el punto medio óptimo depende monótono de los puntos finales. Supongamos que mid [l, r] es el primer punto medio para la subcadena (l, r) que da un resultado óptimo. Se puede demostrar que mid [l, r-1] <= mid [l, r] <= mid [l + 1, r] – esto significa monotonicidad de mid por l y r.

La aplicación de esta optimización reduce la complejidad del tiempo de O (k ^ 3) a O (k ^ 2) porque con s fijo (longitud de subcadena) tenemos m_right (l) = mid [l + 1] [r] = m_left (l + 1 ) Es por eso que los bucles L y M anidados requieren no más de 2k iteraciones en general.

for (int s = 0; s<=k; s++) //s - length(size) of substring for (int l = 0; l+s<=k; l++) { //l - left point int r = l + s; //r - right point if (s < 2) { res[l][r] = 0; //DP base - nothing to break mid[l][r] = l; //mid is equal to left border continue; } int mleft = mid[l][r-1]; //Knuth's trick: getting bounds on m int mright = mid[l+1][r]; res[l][r] = 1000000000000000000LL; for (int m = mleft; m tres) { //relax current solution res[l][r] = tres; mid[l][r] = m; } } } int64 answer = res[0][k]; 

Fuente de ejemplo: Foros de TopCoder

More Interesting

¿Ha pasado una computadora la prueba de Turing, desde el punto de vista matemático y de la informática?

¿Cómo entiende una computadora el concepto de tiempo?

¿Qué es la virtualización de E / S?

¿Qué es la verificación de enlaces de sitios web?

¿Qué evidencia existe de que el Kremlin estaba detrás de los ataques de DNC y cómo podemos estar seguros de su autenticidad? La mayor parte de la evidencia potencial puede ser falsificada.

¿Aprendiste patrones de diseño, control de versiones, desarrollo de tecnología web, marcos ORM y marcos MVC en tu curso CS?

¿Cuáles son algunos de los mejores recursos introductorios (libros, cursos en línea, etc.) en el campo de la IA?

Cómo alcanzar el nivel de matemáticas requerido para participar en el Concurso Internacional de Programación Colegiada

¿Cómo se ve tu i3wm?

¿Cómo pueden los métodos bayesianos ayudar a acelerar el entrenamiento de las redes neuronales profundas?

¿Cómo es trabajar como Especialista en TI (desarrollador web) para el gobierno de los Estados Unidos?

¿Cómo podemos usar la distribución de probabilidad en informática?

Si el mundo en Minecraft está representado en el servidor, y suponemos que el servidor tiene gigabytes de memoria, ¿por qué el mundo no es mucho más grande de lo que es?

¿Pueden las herramientas como WordPress, Webflow, wix, etc. ser un sustituto de la codificación HTML / CSS / JavaScript?

¿Cuál es una buena estrategia para comprar una GPU para un modelo de aprendizaje automático en casa?