Un resumen de la programación dinámica.

1. El problema de la mochila

1 Definición del problema

Cómo determinar si un problema se puede resolver con el problema de la mochila
La característica común del problema de la mochila: dado un objetivo de capacidad de mochila y una matriz de elementos nums , ¿pueden seleccionarse los elementos en nums de cierta manera para obtener el objetivo?
Nota:
1. target y nums pueden ser números o cadenas
2, target puede ser explícito (se ha dado el título), o puede no ser explícito (necesita desenterrar la información del título)
3. Métodos de selección de números comunes: cada elemento solo se puede seleccionar una vez/cada elemento se puede seleccionar varias veces/seleccionado los elementos estan dispuestos

2 Clasificación de problemas

Los tipos comunes de mochilas son los siguientes:
1. Problema de mochila 0/1 : cada elemento se puede seleccionar como máximo una vez
2. Problema de mochila completo : cada elemento se puede seleccionar repetidamente
3. Problema de mochila combinado : se debe considerar el orden
de

Los requisitos de cada problema de mochila también son diferentes, de acuerdo con la clasificación del problema, se puede dividir en los siguientes tipos:
1. El problema de mayor valor : se requiere el valor máximo/mínimo
2. El problema de existencia : si hay ... ………
3. Problema de combinación : Encuentra todas las permutaciones y combinaciones que satisfagan…

3 plantilla de resolución de problemas

01 El problema de la mochila más valiosa

Este problema es el más simple y básico.Después de comprender este problema, puede aprender el problema de la mochila restante con una pequeña modificación.

  • Hay una mochila que puede contener artículos bagWeight, bagWeight=4
  • El peso de cada elemento se expresa como un peso de matriz = {1, 3, 4}
  • El valor de cada elemento se expresa como un valor de matriz = {15, 20, 30}
  • P: Bajo la premisa de no tener sobrepeso, ¿cuál es el valor máximo de artículos que puede contener la mochila?
  • Ideas para resolver problemas:
  1. En primer lugar, hay un límite en el que es fácil pensar: cuando la capacidad de la mochila es 0, no se puede poner nada y el valor máximo es todo 0.
  2. Luego, considere el subproblema más fácil de resolver, asumiendo que solo hay un artículo 1 y que la capacidad máxima de la mochila es 1 ~ bagWeight, entonces la mejor solución puede elegir solo el artículo 1.
  3. Supongamos que se agrega un elemento 2 y la capacidad máxima de la mochila es 1~bagWeight.
    Debido a que el peso del artículo 2 es 3, cuando la capacidad máxima de la mochila es 1 o 2, solo se puede seleccionar un artículo 1, porque no hay espacio para el artículo 2.
    Cuando la capacidad máxima de la mochila es> 2, debe elegir. Esta es la esencia de la regla dinámica. Debe comparar dos esquemas, porque para el elemento 2, solo hay dos posibilidades, tomarlo o no. y, a continuación, comience con Elija la más valiosa de las dos opciones . Por ejemplo, cuando la capacidad máxima de la mochila es 4:
    Esquema 1 : Tome el artículo 2, entonces la capacidad restante de la mochila es 4-3=1, entonces solo necesitamos saber qué se puede obtener cuando la capacidad restante de la la mochila es 1 y no hay artículo i El valor máximo, y luego sumando el valor del artículo 2, es el valor total del plan; plan 2:
    sin tomar el artículo 2, entonces el valor total es en realidad el valor máximo de la mochila cuando la capacidad restante de la mochila es 4, y solo el artículo 1.
    Siga siempre este principio, haga que la capacidad máxima de la mochila sea de 1 a bagWeight, y calcule el valor máximo de artículos que la mochila puede contener cuando solo hay artículos 1 y 2
  4. Recorra toda la matriz de artículos y, para cada submatriz, recorra la capacidad de la mochila de 0 a bagWeight y, finalmente, obtenga el valor máximo de la matriz de artículos completa cuando la capacidad de la mochila sea bagWeight, que es la respuesta
  • Implementación de código
    Primero, necesitamos una matriz bidimensional dp, que usa filas para representar elementos, usa i para hacer ciclos y columnas para representar la capacidad de la mochila (use j para hacer ciclos) , dp[i][j] representa cuándo la mochila la capacidad es j, de i Cómo elegir entre los elementos para obtener el valor máximo. Por ejemplo, la fila 2 y la columna 3 indican: cuando la capacidad de la mochila es 2, cómo elegir entre los artículos 1 y 2 puede obtener el valor máximo.
    Continúe analizando de acuerdo con las ideas de resolución de problemas anteriores:
  1. En primer lugar, hay un límite en el que es fácil pensar: cuando la capacidad de la mochila es 0, no se puede poner nada y el valor máximo es todo 0, es decir, la primera columna de la matriz dp es todo 0 , pd[i][0]=0)
  2. Luego, considere el subproblema más fácil de resolver, suponiendo que solo hay un elemento 1 y que la capacidad máxima de la mochila es 1~bagWeight, entonces la mejor solución solo puede ser elegir el elemento 1, es decir, dp[0] [ j]=valor[0]
  3. Supongamos que se agrega un elemento 2 y la capacidad máxima de la mochila es 1~bagWeight.
    Debido a que el peso del artículo 2 es 3 (peso[i]=3), cuando la capacidad máxima de la mochila es 1, 2 (j=1, j=2), incluso si solo se carga un artículo 2, no se puede cargar. cargado, es decir, dp[i ][j]=dp[i-1][j], si j<peso[i]
    Cuando la capacidad máxima de la mochila > 2 (j>2), es necesario hacer un elección. Esta es la esencia del indicador dinámico. Debe comparar los dos Hay dos esquemas, porque para el elemento 2, solo hay dos posibilidades, ya sea que lo tome o no, y luego elija el que tenga el valor más alto de los dos esquemas, es decir, max (Esquema 1, Esquema 2) . Por ejemplo, cuando la capacidad máxima de la mochila es 4 (j=4):
    Esquema 1 : Tome el elemento 2, luego la capacidad restante de la mochila es 4-3=1, es decir, j-weight[i] , entonces solo necesito saber la capacidad restante de la mochila Cuando es 1, cuando no hay un elemento i, el valor máximo que se puede obtener, es decir, dp[i-1][j-weight[i]] , y luego sumando el valor del elemento 2 (valor[i]), es la solución El valor total, es decir, dp[i-1][j-peso[i]]+valor[i] ;
    esquema 2 : no tomar el elemento 2 , entonces el valor total es en realidad el caso donde solo hay un elemento 1 cuando la capacidad restante de la mochila es 4. A continuación, el valor máximo de la mochila, a saber, dp[i][j]=dp[i-1][j ] .
    Siga siempre este principio, haga que la capacidad máxima de la mochila sea de 1 a bagWeight, y calcule el valor máximo de artículos que la mochila puede contener cuando solo hay artículos 1 y 2
  4. Recorra toda la matriz de artículos y, para cada sub-matriz, recorra la capacidad de la mochila de 0 a bagWeight y, finalmente, obtenga el valor máximo del último artículo cuando la capacidad de la mochila sea bagWeight, que es la respuesta, es decir, dp[total número de artículos-1][ capacidad máxima de la mochila]

Implementación de código (java)

    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        int bagWeight = scanner.nextInt(); // 背包最大容量
        int n = scanner.nextInt(); // 物品数量
        // 物品重量数组
        int[] weight = new int[n];
        for (int i = 0; i < n; i++) {
    
    
            weight[i] = scanner.nextInt();
        }
        // 物品价值数组
        int[] value = new int[n];
        for (int i = 0; i < n; i++) {
    
    
            value[i] = scanner.nextInt();
        }
        // 调用方法求解不超出最大容量的前提下,背包最多能背多大价值的物品
        System.out.println(bags(bagWeight, weight, value));

    }

    public static int bags(int bagWeight, int[] weight, int[] value) {
    
    
        int n = weight.length; // 物品数量
        int[][] dp = new int[n][bagWeight+1]; // dp数组,行表示物品,列表示从0到最大容量
        // 第一列表示背包容量为0时的情况,第一列应该全为0。
        // 由于建dp数组时,java会默认为数组赋0,所以保持第一列为0,更新第二列及以后的即可
        // 从上到下从左到右计算dp,右下角即答案
        for (int i = 0; i < n; i++) {
    
    
            for (int j = 1; j <= bagWeight; j++) {
    
    
                // 第一行表示只能选第一个物品
                if (i == 0) {
    
    
                    dp[i][j] = value[i];
                }
                // 剩余行表示有多个物品可选,需要考虑两种情况
                else {
    
    
                    // 情况1:背包容量就算只装一个物品i也装不下
                    if (j < weight[i]) {
    
    
                        dp[i][j] = dp[i-1][j];
                    }
                    // 情况2:背包容量可以装下物品i,需要考虑两种方案,然后取最大
                    else {
    
    
                        // 方案1:不装物品i
                        // 方案2:装物品i,最大价值为 物品i的价值 加上 去掉物品i的重量后背包剩余容量的最大价值
                        dp[i][j] = Math.max(dp[i-1][j], value[i] + dp[i-1][j-weight[i]]);
                    }
                }
            }
        }
        return dp[n-1][bagWeight]; // 答案是数组的右下角
    }

La matriz dp resultante y la respuesta:

dp = 
[0, 15, 15, 15, 15]
[0, 15, 15, 20, 35]
[0, 15, 15, 20, 35]
answer = 35
  • Avanzado: observe el proceso de cálculo, dp se calcula línea por línea, para ahorrar espacio, podemos guardar solo una línea de datos.
    public static int bags(int bagWeight, int[] weight, int[] value) {
    
    
        int n = weight.length; // 物品数量
        int[] dp = new int[bagWeight+1]; // dp数组,表示从0到最大容量可以装的最大价值
        // 第一个元素表示背包容量为0时的情况。
        // 由于建dp数组时,java会默认为数组赋0,所以保持第一个元素为0,更新第二个元素及以后的即可
        // 从左到右计算dp,最后一个元素即答案
        for (int i = 0; i < n; i++) {
    
    
            // 注意!!!在计算转移方程的过程中,我们需要用到上一次循环得到的dp数组,所以内层循环必须倒序,否则转移方程的dp[j-weight[i]]会被覆盖掉,二维数组不存在这个问题
            for (int j = bagWeight; j > 0; j--) {
    
    
                // 当背包容量可以装下物品i时
                if (j >= weight[i]) {
    
    
                    // 如果只有一个物品可选
                    if (i == 0) {
    
    
                        dp[j] = value[i];
                    }
                    // 如果有多个物品可选
                    else {
    
    
                        // 方案1:不装物品i
                        // 方案2:装物品i,最大价值为 物品i的价值 加上 去掉物品i的重量后背包剩余容量的最大价值
                        dp[j] = Math.max(dp[j], value[i] + dp[j-weight[i]]);
                    }
                }
            }
            System.out.println(Arrays.toString(dp));
        }

        return dp[bagWeight]; // 答案是数组的最后一个元素
    }

        return dp[bagWeight]; // 答案是数组的最后一个元素
    }

Obtenga la matriz dp y la respuesta para cada ciclo:

dp = [0, 15, 15, 15, 15]
dp = [0, 15, 15, 20, 35]
dp = [0, 15, 15, 20, 35]
answer = 35

Se puede encontrar que la esencia del pensamiento es la misma que el proceso de cálculo, pero solo ahorra espacio

problema de mochila restante

La rutina de análisis es básicamente la misma que la del problema de la mochila de mayor valor 01, con las siguientes diferencias:

  • ciclo
  1. 0/1 mochila: la matriz de elementos del bucle externo, la capacidad de la mochila del bucle interno, si se usa una matriz unidimensional rodante, el bucle interno se invierte desde la capacidad máxima;
  2. Mochila completa: matriz de elementos de bucle exterior, capacidad de mochila de bucle interior, secuencia positiva de bucle interior
  3. Mochila combinada: capacidad de la mochila del bucle exterior, matriz de elementos del bucle interior, secuencia positiva del bucle exterior
  4. Mochilas agrupadas: esto es bastante especial y requiere bucles triples: la cantidad de mochilas en el bucle exterior son bolsas, y el bucle interior de dos capas se convierte en plantillas para 1, 2 y 3 tipos de mochila según los requisitos del tema.
  • ecuación de transición de estado
  1. Problema de mayor valor: dp[i] = max/min(dp[i], dp[i-nums]+1) o dp[i] = max/min(dp[i], dp[i-num]+nums );
  2. Hay un problema (bool): dp[i] = dp[i]||dp[i-num];
  3. Problema de combinación: dp[i] += dp[i-num];

4 Análisis de ejemplo

LeetCode 1049. El peso de la última piedra II

  • Abstraer el problema en un problema de mochila (la dificultad está aquí)
  1. Descripción del título : De una pila de piedras, tome dos piedras de peso x e y cada vez. Si x=y, ambas piedras serán trituradas; si x<y, las dos piedras se convertirán en un peso de yx Piedra, encuentre el mínimo peso de la última piedra restante. Es fácil pensar que el valor mínimo es un número no negativo, el mínimo es 0
  2. Conversión de problemas : divida una pila de piedras en dos pilas y encuentre la diferencia de peso mínima entre las dos pilas de piedras (explique en detalle: cada vez que obtenga dos piedras, arroje una al mismo tiempo, y finalmente puede obtener dos pilas de piedras Los pesos de los dos montones de piedras son respectivamente x, y, si x=y, los dos montones de piedras se trituran, si x<y, los dos montones de piedras se convierten en una piedra con un peso de yx, encuentre el valor mínimo de la diferencia de peso entre los dos montones de piedras)
  3. Continúe con la conversión : la suma del peso total de este montón de piedras permanece sin cambios. La situación más perfecta es que los pesos de los dos montones de piedras sean iguales y el desplazamiento sea 0. Para que el peso de las dos pilas de piedras sea lo más igual posible, es necesario que el peso de la primera pila de piedras sea lo más cercano posible a la mitad del peso total, que es suma/2. Esta suma/2 es la capacidad máxima de la mochila, y los artículos seleccionados son todas las piedras, y el peso de cada piedra es el valor del artículo.
  4. Continúe con la conversión al problema del valor máximo de la mochila 01 : Hay una mochila con un peso máximo de suma/2, y le dan un montón de piedras con diferentes pesos. Encuentre el peso máximo de piedras que se pueden cargar sin exceder el peso máximo. de la mochila. ?
  5. Calcule la respuesta : suponga 4. La respuesta obtenida es maxWeight, luego regrese a la pregunta original, el peso de la primera pila de piedras es maxWeight, y el peso de la segunda pila de piedras es sum-maxWeight. El peso de la segunda pila debe ser mayor o igual que la primera pila, por lo que la diferencia de peso entre las dos pilas de piedras es (sum-maxWeight)-maxWeight.
    Para simplificar, la respuesta es sum-2*maxWeight, y maxWeight se puede abstraer en el 01 problema de mochila de mayor valor para resolver.
  • Implementación de código (java)
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] stones = new int[n];
        for (int i = 0; i < stones.length; i++) {
    
    
            stones[i] = scanner.nextInt();
        }
        System.out.println(lastStoneWeightII(stones));
    }

    // 动规
    public static int lastStoneWeightII(int[] stones) {
    
    
        // 非显式的背包最大容量,需要计算
        int sum = 0;
        for (int i = 0; i < stones.length; i++) {
    
    
            sum += stones[i];
        }
        int maxWeight = sum/2; // 背包可以承受的最大重量
        
        // 把石头分成两堆,计算第一堆石头不超出sum/2的最大重量
        // dp表示i个石头时,最大容量为j时,背包最多可以装的重量
        int[] dp = new int[maxWeight+1];
        for (int i = 0; i < stones.length; i++) {
    
    
            // 注意!!用一维数组时,内循环必须倒序,否则状态转移方程用到的dp[j-stones[i]]已经被覆盖掉了
            for (int j = maxWeight; j > 0; j--) {
    
    
                // 边界,第一行,只有一个石头
                if (i == 0 && j >= stones[i]) {
    
    
                    dp[j] = stones[i];
                }
                // 有两个及以上石头
                else {
    
    
                    if (j >= stones[i]) {
    
    
               			// 两种方案(拿石头i或者不拿石头i)取最大重量
                        dp[j] = Math.max(dp[j], stones[i] + dp[j-stones[i]]);
                    }
                }
            }
        }
        // 计算两堆石头的差值,即答案
        return sum-2*dp[maxWeight];
    }

2. Programación dinámica de intervalos

1 plantilla de resolución de problemas

El intervalo DP en realidad busca el valor óptimo en un intervalo.Generalmente
, al establecer el estado de este tipo de problema, puede establecer f[i][j] como el valor óptimo del intervalo ij y
f[i][j], que se obtiene fusionando dos intervalos pequeños. Para dividir estos dos intervalos más pequeños, necesitamos usar una variable de bucle k para enumerar, y la ecuación de transición de estado general es: f [i] [j] = max/min (
f [i][j], f[i][k]+f[k][j]+algo) Necesitamos adaptarnos de acuerdo con el significado real de
este tema. La
plantilla aproximada del intervalo dp es:

for (int len=2;len<=n;len++)
    for (int i=1;i+len-1<=n;i++)
    {
    
    
        int j=i+len-1;
        for (int k=i;k<=j;k++)
            f[i][j]=max/min(f[i][j],f[i][k]+f[k][j]+something)
    }

len enumera la longitud del intervalo, i y j son el punto inicial y final del intervalo, y k se usa para dividir el intervalo.

2 Ejemplo de análisis

Fusión de Niuke y Shizi

  • Tema Descripción

Por favor agregue una descripción de la imagen

  • convertir problema a intervalo dp
  1. Supongamos que hay 5 montones de arena, y el peso de la arena está representado por la matriz nums=[1, 3, 4, 2, 5]. Ahora se requiere el costo mínimo combinado de estos 5 montones de arena (la respuesta es 34). Los siguientes dos esquemas de fusión se dan para comparar
    inserte la descripción de la imagen aquí
    , y el proceso de cálculo del costo total final se obtiene al revés, y se encuentra la regla :
    el costo mínimo de fusión de 5 montones de arena = la suma de los pesos de 5 montones de arena + el costo mínimo de fusión de los dos submontones fusionados la última vez
  2. Un ejemplo para explicar la ley : Para el primer esquema, podemos imaginar que hay una línea divisoria entre 2 y 5, que divide los 5 montones de arena en dos partes. Luego, el costo mínimo de fusión de 5 montones de arena (nums=[1, 3, 4, 2, 5]) = (1+3+4+2+5) + 4 montones de arena (nums=[1, 3, 4, 2 ]) + el costo mínimo combinado de 1 montón de arena (nums=[5])
    Pero de hecho, podemos dividir a la mitad de 2 y 5 (es decir, el primer esquema), o de 4 y 2 Dividido en dos mitades (es decir, el segundo esquema), también se puede dividir en dos mitades de 3 y 4, y así sucesivamente. . . Entonces, necesitamos enumerar todas las situaciones que pueden dividir 5 montones de arena en dos mitades, y luego usar las reglas que resumimos para calcular el costo combinado de cada situación, y luego tomar el mínimo. (El concepto de intervalo se refleja aquí, utilizando un puntero para dividir una matriz completa en dos intervalos)
  3. Imagine recursión : para esta regla, "el costo mínimo de fusión de los dos submontones fusionados la última vez" se puede calcular mediante recursión, que es equivalente a la entrada de recursión. La salida recursiva es el límite, y aquí hay dos límites:
    límite 1: solo hay 1 montón de arena y el costo de fusión es 0;
    Límite 2: solo hay 2 montones de arena y el costo de fusión es la suma de los pesos de los 2 montones de arena;
  4. Ejemplo para explicar la recursividad : Para el ejemplo en 2., el costo mínimo combinado de 4 montones de arena puede ingresarse recursivamente y calcularse de la misma manera. Si el puntero divide los 4 montones de arena en 1, 3 y 4, 2 montones, entonces el costo mínimo de combinación de 4 montones de arena (nums=[1, 3, 4, 2]) = (1+3+4+ 2)+ El costo mínimo de combinación de 2 montones de arena (nums=[1, 3]) + el costo mínimo de combinación de 2 montones de arena (nums=[4, 2]), y 2 montones de arena son salidas recursivas, que se puede calcular directamente con nums
  5. Cambie la recursividad a una regla dinámica : el cálculo recursivo es de afuera hacia adentro, ingresando la profundidad de la recursividad capa por capa, y solo cuando encuentre la salida se calculará capa por capa hasta la capa más externa, y allí habrá muchos cálculos repetidos. La regla dinámica es en realidad la idea de sacrificar el espacio por el tiempo, calcular de adentro hacia afuera, completar el formulario mientras se calcula y evitar muchos cálculos dobles.
    Por lo tanto, el cálculo del gálibo dinámico comienza desde el límite, es decir, primero complete el costo combinado mínimo de 1 montón de arena y 2 montones de arena, y calcule el costo combinado mínimo de 3 montones de arena con base en 1 montón y 2 montones de arena. montones, luego 4 montones, luego 5 montones...
  6. El proceso completo del calibre dinámico :
    calcule la suma por adelantado : sum representa la suma de los pesos de las arenas de la subpila, por ejemplo sum[2][4] representa la suma de los pesos de las arenas de la subpila nums =[4,2,5]
0 1 2 3 4
0 0 4 8 10 15
1 - 0 7 9 14
2 - - 0 6 11
3 - - - 0 7
4 - - - - 0

Inicialice dp : la matriz bidimensional dp del indicador dinámico, que representa el costo mínimo de fusión de la arena de la subpila, por ejemplo, dp[2][4] representa el costo mínimo de fusión de la arena de la subpila nums= [4,2,5].
Si la línea diagonal es 1 montón de arena y la línea sub-diagonal es 2 montones de arena, los números restantes son todos números súper grandes (porque se busca el costo mínimo, si se busca el costo máximo, el resto debe ser todos los números ultrapequeños, lo cual es conveniente Comparar)

0 1 2 3 4
0 0 4 máximo máximo máximo
1 - 0 8 máximo máximo
2 - - 0 7 máximo
3 - - - 0 6
4 - - - - 0

Complete la tabla con la ecuación de transición de estado :
complete la tabla de abajo hacia arriba y de izquierda a derecha, dp[0][4] en la esquina superior derecha de la matriz dp indica el costo mínimo de fusión de nums=[1 ,3,4,2,5], esta es la respuesta que queremos.
Use i y j para representar los dos lados del subarreglo, use k para representar el puntero que puede dividir el subarreglo en dos intervalos, enumere todos los casos de k, calcule el costo combinado y tome el mínimo. La ecuación de transición de estado es la siguiente:
dp[i][j] = min (dp[i][j], sum[i][j] + dp[i][k] + dp[k+1][j])

0 1 2 3 4
0 0 4 12 20 34
1 - 0 7 15 28
2 - - 0 6 17
3 - - - 0 7
4 - - - - 0
  • Implementación de código (java)
    public static void main(String[] args) {
    
    
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        int[] nums = new int[N];
        for (int i = 0; i < nums.length; i++) {
    
    
            nums[i] = scanner.nextInt();
        }
        System.out.println(stonesCombine(N, nums));

    }

    static int stonesCombine(int N,int[] nums) {
    
    
        if (N == 0) {
    
    
            return -1; // 边界,0堆沙子
        }
        int[][] dp = new int[N][N]; // 从i到j的子数组的最小代价
        int[][] sum = new int[N][N]; // 从i到j的子数组的总代价
        // 初始化dp全为最大值,斜对角线全为0,副对角线全为两堆沙子之和
        for (int i = 0; i < N; i++) {
    
    
            for (int j = 0; j < N; j++) {
    
    
                if (i == j) {
    
    
                    dp[i][j] = 0; // 边界1,只有1堆沙子
                }
                else if (i+1 == j) {
    
    
                    dp[i][j] = nums[i] + nums[j]; // 边界2,只有2堆沙子
                }
                else {
    
    
                    dp[i][j] = Integer.MAX_VALUE; // 求最小值,初始化为最大值
                }
            }
        }
        // 计算sum
        for (int i = 0; i < N; i++) {
    
    
            for (int j = i+1; j < N; j++) {
    
    
                if (j == i+1) {
    
    
                    sum[i][j] = nums[i] + nums[j]; // 特殊情况,2堆沙子,1堆沙子总代价为0
                }
                else {
    
    
                    sum[i][j] = sum[i][j-1] + nums[j];
                }
            }
        }
        // 计算dp剩余部分,从下到上,从左到右
        for (int i = N-3; i >= 0; i--) {
    
    
            for (int j = i+2; j < N; j++) {
    
    
                // 枚举所有指针分割成两个区间的情况,取最小
                for (int k = i; k < j; k++) {
    
    
                    dp[i][j] = Math.min(dp[i][j], sum[i][j]+dp[i][k]+dp[k+1][j]);
                }
            }
        }
        // dp右上角即答案
        return dp[0][N-1];
    }
  • Avanzado
    La complejidad del espacio se puede optimizar aún más, y la matriz de suma que representa la suma de los pesos de las sub-matrices puede ser unidimensional

Resumen y Análisis

  1. La programación dinámica es en realidad una idea de sacrificar espacio por tiempo, lo que equivale a registrar los resultados de la recursividad y evitar cálculos repetidos.
  2. La dificultad del problema de la mochila es poder ver si un problema tiene las características del problema de la mochila y abstraerlo en un problema de mochila para resolver
  3. El primer paso para llenar el grupo de indicadores dinámicos es completar primero el límite y calcular el resto de acuerdo con el límite y la ecuación de transición de estado. El límite aquí es en realidad equivalente a la salida de la recursividad, y la ecuación de transición de estado es equivalente a la entrada de la recursividad.
  4. El cálculo de la recursividad es de afuera hacia adentro, y el cálculo de la regla dinámica es de adentro hacia afuera.

URL de referencia

Supongo que te gusta

Origin blog.csdn.net/weixin_46838605/article/details/130422867
Recomendado
Clasificación