1.不同路径
题目解析
算法思路:
1. 状态表示:
对于这种「路径类」的问题,我们的状态表⽰⼀般有两种形式:i. 从 [i, j] 位置出发,巴拉巴拉;ii. 从起始位置出发,到达 [i, j] 位置,巴拉巴拉。这⾥选择第⼆种定义状态表⽰的⽅式:dp[i][j] 表⽰:⾛到 [i, j] 位置处,⼀共有多少种⽅式。2. 状态转移⽅程:
简单分析⼀下。如果 dp[i][j] 表⽰到达 [i, j] 位置的⽅法数,那么到达 [i, j] 位置之前的⼀⼩步,有两种情况:i. 从 [i, j] 位置的上⽅( [i - 1, j] 的位置)向下⾛⼀步,转移到 [i, j] 位置;ii. 从 [i, j] 位置的左⽅( [i, j - 1] 的位置)向右⾛⼀步,转移到 [i, j] 位置。由于我们要求的是有多少种⽅法,因此状态转移⽅程就呼之欲出了: dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 。3. 初始化:
可以在最前⾯加上⼀个「辅助结点」,帮助我们初始化。使⽤这种技巧要注意两个点:i. 辅助结点⾥⾯的值要「保证后续填表是正确的」;ii. 「下标的映射关系」。在本题中,「添加⼀⾏」,并且「添加⼀列」后,只需将 dp[0][1] 的位置初始化为 1 即可。4. 填表顺序:
根据「状态转移⽅程」的推导来看,填表的顺序就是「从上往下」填每⼀⾏,在填写每⼀⾏的时候 「从左往右」。5. 返回值:
根据「状态表⽰」,我们要返回 dp[m][n] 的值。
class Solution {
public int uniquePaths(int m, int n) {
// 1. 创建 dp 表
// 2. 初始化
// 3. 填表
// 4. 返回值
int[][] dp = new int[m + 1][n + 1];
dp[0][1] = 1;
for (int i = 1; i <= m; i++) // 从上往下每⼀⾏
for (int j = 1; j <= n; j++) // 从左往右填写每⼀⾏
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
return dp[m][n];
}
}
2.不同路径2
题目解析
此时有障碍物
算法思路
主要关注的是机器人刚开始站的位置
class Solution {
public int uniquePathsWithObstacles(int[][] ob) {
// 1. 创建 dp 表
// 2. 初始化
// 3. 填表
// 4. 返回值
int m = ob.length, n = ob[0].length;
int[][] dp = new int[m + 1][n + 1];
dp[1][0] = 1;
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
if (ob[i - 1][j - 1] == 0)
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
return dp[m][n];
}
}
3.礼物的最大价值
LCR 166. 珠宝的最高价值 - 力扣(LeetCode)
题目解析
算法思路
class Solution {
public int maxValue(int[][] grid) {
// 1. 创建 dp 表
// 2. 初始化
// 3. 填表
// 4. 返回值
int m = grid.length, n = grid[0].length;
int[][] dp = new int[m + 1][n + 1];
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]) + grid[i - 1][j - 1];
return dp[m][n];
}
}
4.下降路径最小和
题目解析
算法思路
class Solution {
public int minFallingPathSum(int[][] matrix) {
// 1. 创建 dp 表
// 2. 初始化
// 3. 填表
// 4. 返回结果
int n = matrix.length;
int[][] dp = new int[n + 1][n + 2];
for (int i = 1; i <= n; i++)
dp[i][0] = dp[i][n + 1] = Integer.MAX_VALUE;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
dp[i][j] = Math.min(dp[i - 1][j], Math.min(dp[i - 1][j - 1], dp[i - 1][j + 1])) + matrix[i - 1][j - 1];
int ret = Integer.MAX_VALUE;
for (int j = 1; j <= n; j++)
ret = Math.min(ret, dp[n][j]);
return ret;
}
}
5.最小路径和
题目解析
算法思路
class Solution {
public int minPathSum(int[][] grid) {
// 1. 创建 dp 表
// 2. 初始化
// 3. 填表
// 4. 返回值
int m = grid.length, n = grid[0].length;
int[][] dp = new int[m + 1][n + 1];
for (int j = 0; j <= n; j++)
dp[0][j] = Integer.MAX_VALUE;
for (int i = 0; i <= m; i++)
dp[i][0] = Integer.MAX_VALUE;
dp[0][1] = dp[1][0] = 0;
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1];
return dp[m][n];
}
}
6.地下城游戏
题目解析
算法原理
class Solution {
public int calculateMinimumHP(int[][] d) {
// 1. 创建 dp 表
// 2. 初始化
// 3. 填表
// 4. 返回值
int m = d.length, n = d[0].length;
int[][] dp = new int[m + 1][n + 1];
for (int j = 0; j <= n; j++)
dp[m][j] = Integer.MAX_VALUE;
for (int i = 0; i <= m; i++)
dp[i][n] = Integer.MAX_VALUE;
dp[m][n - 1] = dp[m - 1][n] = 1;
for (int i = m - 1; i >= 0; i--)
for (int j = n - 1; j >= 0; j--) {
dp[i][j] = Math.min(dp[i][j + 1], dp[i + 1][j]) - d[i][j];
dp[i][j] = Math.max(dp[i][j], 1);
}
return dp[0][0];
}
}