Esta pregunta es difícil, no es difícil pensar en la idea de la programación dinámica,
sino en cómo considerar los subproblemas, el orden de procesamiento y las ecuaciones de transición de estado.
Primero reformulamos los requisitos del tema como
"En cualquier momento, el valor de salud del caballero x es mayor o igual a 1"
A continuación, definimos de acuerdo con los requisitos del título, suponiendo que el tamaño de la mazmorra sea {mxn}
**
El significado de DP [i] [j] es hacer que el caballero pase de i, j a la esquina inferior derecha durante todo el proceso. El volumen de sangre inicial no es inferior a 1, y finalmente se puede obtener DP [0] [0].
** **
Entonces, ¿es de arriba a la izquierda a la derecha o de abajo a la derecha a la izquierda?
Primero decidamos.
Supongamos que el valor de vida inicial del caballero es x, y use a para representar la matriz bidimensional de la mazmorra.
Según la experiencia de la planificación dinámica habitual del movimiento de matriz bidimensional,
simplificaremos primero el problema y lo dividiremos en los siguientes tres casos.
1. Si el tamaño de la mazmorra es {1x1} (solo 1 cuadrícula)
En este momento, no necesitamos considerar la dirección de la solución del subproblema. El
caballero solo necesita entrar en la única habitación y mantenerla después de que el valor de salud interactúa con esta casa. al menos uno de la sangre
es decir,
resolver para
Como necesitamos obtener el valor más bajo posible de la vida inicial, podemos tomar directamente el signo igual delante de max
2. Si el tamaño de la mazmorra es {1 xn} o {mx 1}
En este momento, ¡debemos considerar la dirección en la que se resuelve el subproblema!
Tenemos un {1} x n (1 filas y n columnas) como un ejemplo de la mazmorra
esta es una mazmorra
Supongamos que superior izquierda (a [0] [0] ) a la parte inferior derecha (a [0] [n- 1])
a través de la primera rejilla, similar a la anterior "1",
no
, pero esta vez, si no saben una [0] [1] ~ a [0] [n-1] El valor
de dp [0] [0] no se puede derivar porque no conocemos la siguiente cuadrícula, por lo que no podemos determinar el valor de salud inicial.
¡Por lo tanto, debemos considerar la evolución desde la parte inferior derecha a la superior izquierda!
Por lo tanto, primero consideramos que si comenzamos desde la última cuadrícula a [0] [n-1], ya que también desencadena una interacción de valor de vida
, similar a "1",
movemos el punto de partida a la izquierda a [0] [n -2]
Si comenzamos desde un [0] [n-2] con el valor de salud x, entonces
estamos obligados a cambiar la tercera línea de arriba,
para que podamos fusionar las expresiones de la segunda y tercera línea Y obtén el siguiente resultado
¿En este momento, encontramos milagrosamente que la fórmula a la derecha después de la fusión no es DP [0] [n-1]? ?
Por lo tanto, sustituimos DP [0] [n-1] para obtener, y
luego cambiamos el término a [0] [n-2] en la segunda línea de expresión, para que sea
fácil
obtener el requisito mínimo, tomar el signo igual, obtener
Para esta fórmula, generalizamos a la conclusión general de esta mazmorra de formas
De manera similar, para la mazmorra de {mx 1} (m filas y 1 columna), podemos sacar una conclusión similar: de
esta manera, resolvimos la situación de una fila con múltiples columnas, o una columna con múltiples filas
3. En general, eso es {mxn} (la mazmorra tiene m filas yn columnas, las cuales son> 1).
Como ya hemos concluido en "2",
en la premisa de que solo puede elegir moverse hacia la derecha o hacia abajo, una
sola fila O una sola columna de mazmorras, el valor de DP de cada cuadrícula solo está relacionado con esta fila o columna
Incluso si hay m filas yn columnas,
si comenzamos desde la última fila, entonces solo tenemos una ruta, es decir, yendo hacia la derecha (no tiene nada que ver con el valor de a en otras filas),
si enviamos desde la última columna, entonces solo tenemos una ruta, a saber Todo el camino hacia abajo (no tiene nada que ver con el valor de a en otras columnas),
por lo que inicializamos las dos filas inferiores y la más a la derecha de las m filas yn columnas de acuerdo con las dos últimas fórmulas en "2"
En otras palabras, para llenar la matriz DP,
podemos inicializar la parte gris en la figura a continuación de acuerdo con la conclusión obtenida anteriormente.
A continuación, comenzamos a llenar desde un [m-2] [n-2], y podemos llenar el m-ésimo primero. 2 filas, también puede llenar la columna n-2
primero. Completemos primero el comportamiento m-2, como se muestra a continuación (en adelante, usamos verde para indicar la cuadrícula inicializada).
Según la experiencia en el tratamiento de tales problemas, sub-problema Bloqueado en una cuadrícula local de 2x2.
En el orden de la figura anterior, podemos asegurarnos de que los valores DP debajo de la cuadrícula i, j, el lado derecho y la parte inferior derecha del valor DP a calcular se conozcan cada vez
. Como se muestra en
la siguiente figura De i, j a i + 1, j + 1, solo tenemos dos opciones, a saber
(1) i, j-mover hacia abajo-> i + 1, j-mover hacia la derecha-> i + 1, j + 1
(2) i, j-desplazamiento a la derecha-> i, j + 1-desplazamiento hacia abajo-> i + 1, j + 1
Si (1),
supongamos que la vida inicial es x, existe
su El significado es que la vida inicial no es menor que 1, y el valor mínimo requerido después de i, j no es menor que 1 y no menor que i + 1, j
Por lo tanto,
considerando la fórmula recursiva anterior, podemos asegurarnos de que los DP que se hayan obtenido no sean inferiores a 1 (también se puede entender que el volumen sanguíneo inicial no debe ser inferior a 1)
. La fórmula anterior se puede simplificar
a (2).
Luego está la clave, porque hay dos caminos por recorrer, queremos encontrar el valor mínimo requerido,
por lo tanto, siempre que haya uno que cumpla con el valor de vida es mayor o igual a 1, por lo tanto, tomamos las dos desigualdades anteriores O,
es decir, dejemos que x es mayor o igual que el menor de los dos máximos
Es decir, cuando 0 ≤ i ≤ m-2 y 0 ≤ j ≤ n-2
cuando i = m-1 y
j = n-1 de
esta manera, obtenemos la ecuación de transición de estado de la programación dinámica
class Solution:
def calculateMinimumHP(self, dungeon: List[List[int]]) -> int:
m = len(dungeon)
n = len(dungeon[0])
if m == 1 and n == 1:#1x1的地牢
return max(1,1-dungeon[0][0])
elif m == 1 and n != 1:#1xn的地牢
newlist = []
for i in range(n):
newlist.append(-1)
newlist[-1] = max(1,1-dungeon[0][-1])
for i in range(n-1):
tempindex = n - i - 2
newlist[tempindex] = max(1,newlist[tempindex+1] - dungeon[0][tempindex])
return newlist[0]
elif m != 1 and n == 1:#nx1的地牢
newlist = []
for i in range(m):
newlist.append(-1)
newlist[-1] = max(1,1-dungeon[-1][0])
for i in range(m-1):
tempindex = m - i - 2
newlist[tempindex] = max(1,newlist[tempindex+1] - dungeon[tempindex][0])
return newlist[0]
#以下针对mxn的地牢,m和n都大于1
#初始化一个m行n列的dplist
print('地牢的size为',m,n)
newlist = []
for i in range(m):
templist = []
for j in range(n):
templist.append(-1)
newlist.append(templist)
#我们先初始化最下面一行和最右边一列
#先初始化最右下角的
newlist[m-1][n-1] = max(1,1 - dungeon[-1][-1])
tempinit = newlist[-1][-1]
#最下面一行,共n-1个待补充的数字
for i in range(n-1):
tempindex = n - i - 2
newlist[-1][tempindex] = max(1,newlist[-1][tempindex+1] - dungeon[-1][tempindex])
#最右边一列,共m-1个待补充的数字
for j in range(m-1):
tempindex = m - j - 2
newlist[tempindex][-1] = max(1,newlist[tempindex+1][-1] - dungeon[tempindex][-1])
#从[m-2][n-2]开始填充,一直到[0][0],共(m-1)x(n-1)个
#先从倒数第二行倒数第二列开始,然后是倒数第二行倒数第三列,......
for i in range(m-1):
tempi = m - i - 2
for j in range(n-1):
tempj = n - j - 2
newlist[tempi][tempj] = max(1,min(newlist[tempi+1][tempj],newlist[tempi][tempj+1])-dungeon[tempi][tempj])
print(newlist)
return newlist[0][0]