¿Cuáles son algunos conceptos que debo saber antes de aprender programación dinámica?

  1. Recursión : pienso en la programación dinámica como Recursion + Memoization. Verá que los problemas de programación dinámica tienen una subestructura óptima. Lo que esto significa es que una solución para [math] f (n) [/ math] es óptima si y solo si una solución para [math] f (nk) [/ math] es óptima. Entonces, todo lo que necesitas hacer es pensar de forma recursiva. Defina la propiedad recursiva y simplemente amplíela.
    Tomemos un ejemplo: la mayor secuencia creciente
    Por lo tanto, se le proporciona una matriz y desea encontrar la subsecuencia de mayor crecimiento de esta matriz. Como hay subsecuencias [matemáticas] 2 ^ n [/ matemáticas], el enfoque ingenuo no funcionará. Intentemos encontrar su propiedad recursiva. Deje que [math] f (i) [/ math] sea la subsecuencia de mayor crecimiento de [math] a_ {1}, .. a_ {i} [/ math] que tiene [math] a_i [/ ​​math] como último elemento . Es fácil ver que es para algunos [matemática] k [/ matemática], si [matemática] a_k <a_i [/ ​​matemática] entonces [matemática] f (i) = f (k) + 1 [/ matemática]. Si iteramos sobre todas [matemáticas] k [/ matemáticas], de [matemáticas] 1 [/ matemáticas] a [matemáticas] i-1 [/ matemáticas] y verificamos cada valor y actualizamos [matemáticas] f (i) [/ matemáticas ] para ser el máximo de todas [matemáticas] f (k) + 1 [/ matemáticas], habremos terminado. Eso es todo, tenemos nuestra propiedad recursiva. Todo lo que queda por hacer ahora es codificarlo. Lo cual será bastante fácil de hacer si sabes recurrencia. Si no conoce la memorización, lea sobre ella. Aquí hay un código de muestra que lo hace:

    int mem[1000] = {0};
    mem[0] = 1; int lis(int ar[], int n){
    if(mem[n-1] == 0 ){
    mem[n-1] = 1;
    for(int i=0; i<n-1; i++){
    if(ar[i] < ar[n-1])
    mem[n-1] = max(mem[n-1], lis(i)+1);
    }
    }
    return mem[n-1];
    }

    int mem[1000] = {0};
    mem[0] = 1; int lis(int ar[], int n){
    if(mem[n-1] == 0 ){
    mem[n-1] = 1;
    for(int i=0; i<n-1; i++){
    if(ar[i] < ar[n-1])
    mem[n-1] = max(mem[n-1], lis(i)+1);
    }
    }
    return mem[n-1];
    }

  2. Pensamiento de abajo hacia arriba . Aunque la recursividad + la memorización es buena, requieren espacio de pila adicional y, por lo tanto, construir la solución desde abajo siempre es mejor (aunque no más fácil). Lo que esto significa es que, use [math] f (1), f (2), .. f (k) [/ math] para encontrar una solución a [math] f (n) [/ math]. Calcule esos [math] f (i) [/ math] primero y luego calcule [math] f (n) [/ math] usándolos. Esto hará que la solución sea iterativa y, por lo tanto, será más rápida que la de memorización. La versión de memorización anterior se puede traducir a un enfoque ascendente muy fácilmente:

    int lis(int ar[], int n){
    int *mem = new int[n];
    for(int i=0; i<n; i++){
    mem[i] = 1;
    for(int j=0; j<i; j++){
    if(ar[j] < ar[i])
    mem[i] = max(mem[i], mem[j] +1);
    }
    }
    return mem[n-1];
    }

  3. Práctica: La práctica te hará mejor. Encuentre preguntas e intente resolverlas por su cuenta.

Combinatoria, relaciones de recurrencia (en combinatoria), análisis algorítmico básico, recursividad y divide y vencerás. En CLRS puede que le resulte fácil seguir la programación dinámica después de ser minucioso con estos.

NOTA: Algunos cursos MOOC en línea enseñan algoritmos codiciosos antes de enseñar algoritmos de programación dinámica. Una vez que enseñan el algoritmo codicioso para el problema de la mochila fraccional, continúan explicando por qué ese enfoque no funciona con el problema de la mochila 0/1.

Si me falta algo, corrígeme.

Creo que el profesor Thomas Cormen tendrá una respuesta mucho mejor. Estaría interesado en saber su opinión al respecto.

EDITAR: No he mencionado el concepto de existencia de una subestructura óptima, suponiendo que la aprenderá cuando aprenda programación dinámica.

More Interesting

¿Cómo es que la mayoría de las empresas solicitan específicamente estructuras de datos y algoritmos? ¿Qué sucede cuando un adicto a los algoritmos con solo conocimiento de C ++ o Java es aceptado en una empresa que utiliza tecnologías web, aprende el marco utilizado desde cero?

¿Cómo saben las computadoras cuándo comienza y termina una cadena binaria?

Cómo resolver SPOJ.com - Problema GERGOVIA en SPOJ

Cómo restar enteros usando un algoritmo

¿Para qué sirven los bordes traseros en el algoritmo Ford-Fulkerson?

¿Debo ir a un curso de algoritmos o comenzar a resolver problemas en TopCoder / CodeChef, etc.?

Cómo hacer un bot de chat usando Python implementando algoritmos de aprendizaje automático (como SVM, Naive Bayes, Random Forest, etc.)

¿Puedo obtener una breve descripción general del documento 'Generación precisa de hologramas utilizando el método basado en capas y el algoritmo de transformación de Fourier iterativo'?

En el algoritmo de Mo, ¿por qué clasificamos las consultas primero en función del número de bloque y luego (si hay un empate) en función del punto final derecho? ¿Cuál es la intuición detrás de esto?

¿Qué debo aprender a continuación para mejorar mi última capa?

¿Cuáles son algunos algoritmos / métodos de aprendizaje automático altamente efectivos?

¿Cuál es el mejor algoritmo para realizar la extracción de características para el reconocimiento óptico de caracteres?

Soy nuevo en Quora y no entiendo si las preguntas de coeficiente intelectual son una tendencia constante o si estoy atrapado en alguna forma de algoritmo infernal. Si es así, ¿cómo escapo?

¿Cuál es el algoritmo del cerebro humano?

¿Existe algún estándar de algoritmo de programación de elevadores públicos?