"Oferta de Sword Finger" Día 29: La suma de ruta mínima de la cuadrícula mxn

¡He preparado 1,000 libros electrónicos y 100 mapas mentales de alta definición en varios campos de la informática, y responderé a [Recursos] después de prestar atención para conseguirlo! ¡Incluso puede responder [introducción] para unirse al grupo introductorio de BAT!

"Oferta de Sword Finger" Día 29: La suma de ruta mínima de la cuadrícula mxn

En el artículo anterior, a través del análisis, completamos con éxito el problema de programación dinámica de "suma de ruta mínima triangular". En esta sección, continuamos examinando un tipo de pregunta similar para comprender completamente este problema de "suma de ruta". No hay mucho que decir, primero mira el tema:

01, análisis de tema


Pregunta 64: Suma de ruta mínima


Dada una cuadrícula mxn que contiene números enteros no negativos, busque una ruta desde la esquina superior izquierda hasta la esquina inferior derecha para que la suma de los números en la ruta sea la más pequeña.


Nota: solo puede moverse un paso hacia abajo o hacia la derecha a la vez.

Ejemplo:

输入:
[
  [1,3,1],
  [1,5,1],
  [4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。

¡Esta pregunta tiene cierto grado de dificultad! Si no tiene ideas, revise el contenido de aprendizaje del artículo anterior.

¡No se recomienda mirar la solución directamente!

02, ilustración del tema


Primero, analizamos el tema, buscando un camino mínimo y , ¿qué significa eso? Supongamos que tenemos un rectángulo m * n: [[1,3,1], [1,5,1], [4,2,1]]
"Oferta de Sword Finger" Día 29: La suma de ruta mínima de la cuadrícula mxn

La suma de la ruta mínima desde la esquina superior izquierda a la esquina inferior derecha , podemos ver fácilmente que es 1-3-1-1-1, esta ruta, el resultado es igual a 7.

El tema está claro, seguimos analizando. Esta pregunta es la misma que la anterior para encontrar la ruta mínima suma del triángulo, la pregunta claramente se ajusta a que se puede construir a partir de la solución óptima del subproblema , por lo que consideramos usar programación dinámica para resolverlo. Primero, definimos el estado:

dp[i][j] : 表示包含第i行j列元素的最小路径和

Del mismo modo, porque cualquier camino a la esquina inferior derecha pasará por el elemento [0,0]. Por tanto, necesitamos inicializar dp [0] [0].


dp[0][0] = [0][0]位置所在的元素值

Continuando con el análisis, según las condiciones que da el título, si requerimos dp [i] [j], entonces debe haberse movido desde arriba o hacia la izquierda. Como se muestra abajo:

"Oferta de Sword Finger" Día 29: La suma de ruta mínima de la cuadrícula mxn

5, solo puede moverse desde 3 o 1
2, solo puede moverse desde 5 o 4,
4, moverse desde 1
3, moverse desde 1
(la posición roja debe moverse desde la posición azul)
y luego obtenemos la ecuación de transición de estado:

dp [i] [j] = min (dp [i-1] [j], dp [i] [j-1]) + grid [i] [j]
También debemos considerar dos casos especiales:

  • La fila superior solo se puede mover desde la izquierda (1-3-1)
  • La columna más a la izquierda solo se puede mover desde arriba (1-1-4).
    "Oferta de Sword Finger" Día 29: La suma de ruta mínima de la cuadrícula mxn
    Finalmente, debido a que nuestro objetivo es caminar desde la esquina superior izquierda a la esquina inferior derecha, la suma de ruta mínima de toda la cuadrícula es en realidad la suma de ruta mínima que contiene los elementos en la esquina inferior derecha . cual es:

Supongamos: la longitud de dp es ly el
resultado final es: dp [l-1] [len (dp [l-1]) - 1] En
resumen, hemos terminado el análisis y hemos realizado un total de 4 pasos:

1. Definir el estado
2. Resumir la ecuación de transición de estado
3. Analizar los casos especiales que la ecuación de transición de estado no puede satisfacer.
4. Obtenga la solución final

03, ejemplo de idioma GO


Según el análisis anterior, el código se puede obtener de la siguiente manera:

![](https://s4.51cto.com/images/blog/202101/27/5486729781abbd79236bd4939d76a6ac.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)func minPathSum(grid [][]int) int {
 l := len(grid)
 if l < 1 {
  return 0
 }
 dp := make([][]int, l)
 for i, arr := range grid {
  dp[i] = make([]int, len(arr))
 }
 dp[0][0] = grid[0][0]
 for i := 0; i < l; i++ {
  for j := 0; j < len(grid[i]); j++ {
   if i == 0 && j != 0 {
    dp[i][j] = dp[i][j-1] + grid[i][j]
   } else if j == 0 && i != 0 {
    dp[i][j] = dp[i-1][j] + grid[i][j]
   } else if i !=0 && j != 0 {
    dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
   }
  }
 }
 return dp[l-1][len(dp[l-1])-1]
}

func min(a, b int) int {
 if a > b {
  return b
 }
 return a
}

resultado de la operación:
"Oferta de Sword Finger" Día 29: La suma de ruta mínima de la cuadrícula mxn

Del mismo modo, al ejecutar el código anterior, encontramos que la memoria utilizada es demasiado grande. ¿Hay alguna forma de comprimir la memoria? A través de la observación, encontramos que en el proceso de calcular la suma de ruta mínima de cada nodo desde la esquina superior izquierda a la esquina inferior derecha, solo necesitamos usar los datos que se han acumulado antes, y no accederemos a los datos del elemento anterior. de nuevo . El dibujo es el siguiente: (Todos ven que este proceso se parece a un barrido de minas. De hecho, si estudia el complemento de barrido de minas, encontrará que hay un método de análisis que es bastante similar a este tipo de método de análisis en el núcleo algoritmo de barrido de minas. No entraré en él aquí).

"Oferta de Sword Finger" Día 29: La suma de ruta mínima de la cuadrícula mxn
El código optimizado es el siguiente:


func minPathSum(grid [][]int) int {
 l := len(grid)
 if l < 1 {
  return 0
 }
 for i := 0; i < l; i++ {
  for j := 0; j < len(grid[i]); j++ {
   if i == 0 && j != 0 {
    grid[i][j] = grid[i][j-1] + grid[i][j]
   } else if j == 0 && i != 0 {
    grid[i][j] = grid[i-1][j] + grid[i][j]
   } else if i !=0 && j != 0 {
    grid[i][j] = min(grid[i-1][j], grid[i][j-1]) + grid[i][j]
   }
  }
 }
 return grid[l-1][len(grid[l-1])-1]
}

func min(a, b int) int {
 if a > b {
  return b
 }
 return a
}

resultado de la operación:

"Oferta de Sword Finger" Día 29: La suma de ruta mínima de la cuadrícula mxn
Java:

class Solution {
    public int minPathSum(int[][] grid) {
        int l = grid.length;
        if (l < 1) {
            return 0;
        }
        for(int i = 0; i < l; i++)  {
            for(int j = 0; j < grid[i].length; j++)  {
                if (i == 0 && j != 0) {
                    grid[i][j] = grid[i][j-1] + grid[i][j];
                } else if (j == 0 && i != 0) {
                    grid[i][j] = grid[i-1][j] + grid[i][j];
                } else if (i !=0) {
                    grid[i][j] = min(grid[i-1][j], grid[i][j-1]) + grid[i][j];
                }
            }
        }
        return grid[l-1][grid[l-1].length - 1];
    }

    public int min(int a, int b) {
        return a > b ? b : a;
    }

}

resultado de la operación:
"Oferta de Sword Finger" Día 29: La suma de ruta mínima de la cuadrícula mxn

Pensamientos después de la clase: ¿Cuál es la diferencia entre el problema de ruta y clase y el problema de subsecuencia anterior?

Supongo que te gusta

Origin blog.51cto.com/15076236/2608566
Recomendado
Clasificación