Сложность: hard
Демоны захватили принцессу и заточили её в правом нижнем углу подземелья. Подземелье состоит из m x n комнат, расположенных в виде двумерной сетки. Наш отважный рыцарь изначально находится в левом верхнем углу и должен пробиться через подземелье, чтобы спасти принцессу.
У рыцаря есть начальное количество очков здоровья, представленное положительным целым числом. Если в какой-то момент его очки здоровья упадут до 0 или ниже, он немедленно умрёт.
Некоторые комнаты охраняются демонами (представлены отрицательными числами), поэтому рыцарь теряет здоровье, заходя в эти комнаты; другие комнаты либо пусты (представлены как 0), либо содержат магические шары, увеличивающие здоровье рыцаря (представлены положительными числами).
Чтобы как можно быстрее добраться до принцессы, рыцарь решает двигаться только вправо или вниз на каждом шаге.
Верните минимальное начальное количество здоровья рыцаря, чтобы он мог спасти принцессу.
Учтите, что любая комната может содержать угрозы или усиления, включая первую комнату, в которую входит рыцарь, и последнюю комнату, где заточена принцесса.
Пример:
Input: dungeon = [[-2,-3,3],[-5,-10,1],[10,30,-5]]
Output: 7
Explanation: The initial health of the knight must be at least 7 if he follows the optimal path: RIGHT-> RIGHT -> DOWN -> DOWN.
👨💻 Алгоритм:
1⃣Определяем матрицу dp[row][col], где элемент dp[row][col] указывает минимальное количество очков здоровья, которое потребуется рыцарю, начиная с соответствующей ячейки подземелья dungeon[row][col], чтобы добраться до цели.
2⃣Для расчета значений матрицы dp начинаем с правого нижнего угла подземелья и идем в порядке справа-налево и снизу-вверх. Для каждой ячейки подземелья рассчитываем соответствующее значение dp[row][col].
3⃣Значение dp[row][col] определяется следующими условиями:
Если возможно, сделав шаг вправо из текущей ячейки подземелья, рыцарь может нуждаться в right_health очках здоровья.
Если возможно, сделав шаг вниз из текущей ячейки подземелья, рыцарь может нуждаться в down_health очках здоровья.
Если существует хотя бы одна из вышеуказанных альтернатив, берём минимальное значение из них для dp[row][col].
Если ни одна из вышеуказанных альтернатив не существует, то есть мы находимся в целевой ячейке, возможны два случая:
Если текущая ячейка содержит магический шар, то достаточно одного очка здоровья.
Если текущая ячейка содержит демона, то рыцарь должен иметь одно очко здоровья плюс очки урона, которые нанесет демон.
😎 Решение:
class Solution {
int inf = Integer.MAX_VALUE;
int[][] dp;
int rows, cols;
public int getMinHealth(int currCell, int nextRow, int nextCol) {
if (nextRow >= this.rows || nextCol >= this.cols) return inf;
int nextCell = this.dp[nextRow][nextCol];
return Math.max(1, nextCell - currCell);
}
public int calculateMinimumHP(int[][] dungeon) {
this.rows = dungeon.length;
this.cols = dungeon[0].length;
this.dp = new int[rows][cols];
for (int[] arr : this.dp) {
Arrays.fill(arr, this.inf);
}
int currCell, rightHealth, downHealth, nextHealth, minHealth;
for (int row = this.rows - 1; row >= 0; --row) {
for (int col = this.cols - 1; col >= 0; --col) {
currCell = dungeon[row][col];
rightHealth = getMinHealth(currCell, row, col + 1);
downHealth = getMinHealth(currCell, row + 1, col);
nextHealth = Math.min(rightHealth, downHealth);
if (nextHealth != inf) {
minHealth = nextHealth;
} else {
minHealth = currCell >= 0 ? 1 : 1 - currCell;
}
this.dp[row][col] = minHealth;
}
}
return this.dp[0][0];
}
}Ставь 👍 и забирай 📚 Базу знаний
