Planificación dinámica-Introducción

Programación dinámica

Wikipedia define la programación dinámica de la siguiente manera:

La programación dinámica es un método para resolver un problema complejo dividiéndolo en una colección de subproblemas más simples, resolviendo cada uno de esos subproblemas una sola vez y almacenando sus soluciones.
Ref: programación dinámica

En otras palabras, la programación dinámica debe tener las siguientes tres características:

  1. Descomponga el problema original en varios subproblemas similares. (Énfasis en "subproblemas similares")
  2. Todos los subproblemas deben resolverse solo una vez. (Énfasis en "solo resolver una vez")
  3. Almacene la solución al subproblema. (Énfasis en "guardar")

Entonces, ¿cómo juzgar si un problema puede resolverse mediante programación dinámica?

Si se mantiene el principio de optimización para resolver el problema, puede resolverse mediante programación dinámica

Independientemente del estado inicial y la decisión inicial del proceso, las decisiones restantes deben formar una secuencia de decisión óptima en relación con el estado generado por la decisión inicial. Aprendamos programación dinámica a través de algunos ejemplos.

1. El problema de la torre numérica

Descripción del problema

        7 
      3   8 
    8   1   0 
  2   7   4   4 
4   5   2   6   5

Hay una torre de conteo de hileras con varios números. P. Desde el punto más alto hasta la parte inferior de la torre, ¿cuál es la suma más grande de los números pasados ​​en todos los caminos?
Como se muestra en la figura anterior, es una torre de conteo de 5 filas, en la cual el camino de 7-3-8-7-5 pasa a través del número y el máximo es 30.

Ideas de soluciones

Ante el problema de la torre numérica, obviamente no es factible utilizar el algoritmo codicioso. Por ejemplo, si se utiliza el algoritmo codicioso, la ruta seleccionada debe ser 7-8-1-7-1-5, y el número después del número es solo 28 No es el más grande. Con la búsqueda profunda DFS, es fácil calcular la complejidad del tiempo como O (2N-1) (porque cada número tiene dos opciones de abajo a la izquierda y abajo a la derecha), cuanto mayor sea el número de líneas, más tiempo de espera.

Por lo tanto, el algoritmo de programación dinámica es necesario para el problema de la torre de datos.

① Podemos atravesar de arriba a abajo.

Se puede encontrar que si desea pasar un número, solo puede alcanzarlo desde el número en la esquina superior izquierda o la esquina superior derecha.

Entonces, obviamente, al pasar cualquier número A, el número más grande por el que pasa la ruta es el número B en la esquina superior izquierda del número A y el número C en la esquina superior derecha. Ese, más ese número A.

Por lo tanto, la ecuación de transición de estado es: [Oficial]

Donde i, j representa el número de filas y columnas, dp representa la suma máxima de almacenamiento y num representa el número en la posición.

[Oficial]Indica la esquina superior izquierda e [Oficial]indica la esquina superior derecha.

Para ilustrar con un ejemplo: al pasar el número 1 en la tercera fila, primero miramos la suma máxima del número 3 en la esquina superior izquierda y el número 8 en la esquina superior derecha. Obviamente, 3 solo tiene una ruta de 7-3, por lo que la suma máxima es 10; 8 obviamente también tiene solo una ruta de 7-8, la suma máxima es 15; la mayor de las dos es 15, por lo que la suma máxima que se puede alcanzar después de 1 es 15 + 1 = 16.

Esto atraviesa paso a paso, y finalmente se obtiene la suma máxima que se puede alcanzar después de pasar por cada posición, siempre que el valor máximo se encuentre en la fila inferior y la salida.

② También podemos atravesar de abajo hacia arriba.

No importa si una ruta va de arriba hacia abajo o de abajo hacia arriba, el número y el número que pasa son los mismos, por lo que esta pregunta puede convertirse en una demanda: la suma del número más grande que pasa del fondo al punto más alto.

El método de escritura es el mismo que el recorrido secuencial, excepto que cuando el estado transita, el máximo se toma de la esquina inferior izquierda y la esquina inferior derecha del número. En comparación con el recorrido secuencial, la ventaja de escribir en el orden inverso es que el proceso de encontrar la última línea máxima en el último paso es menor, y el valor almacenado en el punto más alto se puede generar directamente.

Implementación de código

#include <stdio.h>
#include <algorithm>
using namespace std;//这里以顺序遍历为例
int num[1005][1005];//用于储存数塔每个位置的数字
int dp[1005][1005];//用于储存经过数塔每个位置所能达到的最大和
int main()
{
    int r;
    scanf("%d",&r);//输入数塔行数
    for(int i=1;i<=r;i++)
        for(int j=1;j<=i;j++)
            scanf("%d",&num[i][j]);
    //输入数塔数据,注意i和j要从1开始,防止数组越界
    for(int i=1;i<=r;i++)//共计r行
        for(int j=1;j<=i;j++)//每行有j个数字
            dp[i][j]=max(dp[i-1][j],dp[i-1][j-1])+num[i][j];
    //经过该数字的最大和,为左上角和右上角中的max,再加上该数字
    int ans=0;
    for(int i=1;i<=r;i++)
        ans=max(ans,dp[r][i]);//从最后一行中找到最大数
    printf("%d\n",ans);//就是答案
    return 0;
}

Supongo que te gusta

Origin www.cnblogs.com/fluxation/p/12693486.html
Recomendado
Clasificación