地下城游戏(困难)
2020年7月12日
题目来源:力扣
解题
最近都很忙,今天这道题简单看了题目,觉得是没什么坑的一道DFS,以下代码来自题解
class Solution {
public int calculateMinimumHP(int[][] dungeon) {
return dfs(dungeon, dungeon.length, dungeon[0].length, 0, 0);
}
private int dfs(int[][] dungeon, int m, int n, int i, int j) {
// 到达终点,递归终止。
if (i == m - 1 && j == n - 1) {
return Math.max(1 - dungeon[i][j], 1);
}
// 最后一行,只能向右搜索。
if (i == m - 1) {
return Math.max(dfs(dungeon, m, n, i, j + 1) - dungeon[i][j], 1);
}
// 最后一列,只能向下搜索。
if (j == n - 1) {
return Math.max(dfs(dungeon, m, n, i + 1, j) - dungeon[i][j], 1);
}
// 向下搜索 + 向右搜索,得到(i, j)点的后续路径所要求的最低血量 Math.min(dfs(i + 1, j), dfs(i, j + 1)),
// 又因为(i, j)点本身提供血量dungeon[i][j], 因此从(i, j)开始所需的最低血量为 Math.min(dfs(i + 1, j), dfs(i, j + 1)) - dungeon[i][j]
// 因为骑士的血量不能小于1,因此要和1取个max。
return Math.max(Math.min(dfs(dungeon, m, n, i + 1, j), dfs(dungeon, m, n, i, j + 1)) - dungeon[i][j], 1);
}
}
因为搜索时会有大量重复计算的分支,加上记忆化数组
class Solution {
int[][] memo; // 定义记忆化数组
public int calculateMinimumHP(int[][] dungeon) {
memo = new int[dungeon.length][dungeon[0].length];
return dfs(dungeon, dungeon.length, dungeon[0].length, 0, 0);
}
private int dfs(int[][] dungeon, int m, int n, int i, int j) {
// 到达终点,递归终止。
if (i == m - 1 && j == n - 1) {
return Math.max(1 - dungeon[i][j], 1);
}
// 如果memo数组中有值,直接取出并返回,不进行后续的搜索。
if (memo[i][j] > 0) {
return memo[i][j];
}
// 同解法一,向右搜+向下搜
int minRes = 0;
if (i == m - 1) {
minRes = Math.max(dfs(dungeon, m, n, i, j + 1) - dungeon[i][j], 1);
} else if (j == n - 1) {
minRes = Math.max(dfs(dungeon, m, n, i + 1, j) - dungeon[i][j], 1);
} else {
minRes = Math.max(Math.min(dfs(dungeon, m, n, i + 1, j), dfs(dungeon, m, n, i, j + 1)) - dungeon[i][j], 1);
}
// 将结果存入memo数组
return memo[i][j] = minRes;
}
}