一.第62题 不同路径I
1.1题目要求
一个机器人位于一个 m x n 网格的左上角
(起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
1.2动态规划解析
(1) 定义动态规划
- 定义 f[i][j] 为到达位置 (i,j)(i,j) 的不同路径数量。
- 那么 f[m-1][n-1]就是最终的答案。
- 而 f[0][0] = 1是一个明显的起始条件,因为到达起点只有一条路线。
(2)确定状态转移方程
只能往下或者往右 移动,按照可选方向进行分析:
- 当前位置只能「往下」移动得到,即有 f[i][j] = f[i-1][j]
- 当前位置只能「往右」移动得到,即有 f[i][j] = f[i][j-1]
- 当前位置即能「往下」也能「往右」移动得到,
即有 f[i][j] = f[i][j-1] + f[i-1][j]
1.3编程求解
把刚刚的状态转移方程转化为编程语言:
- 只能向下移得到,说明它是在第一列,只能通过向下移得到。
编程语言:j=0,i>0 (i>0说明不是起点) - 只能通过左移得到,说明在第一行,只能通过向左移得到。
编程语言:i=0,j>0 (j>0说明不是起点) - 即可向下又可向左得到,说明不在第一行或第一列。
编程语言:i>0,j>0
代码示例如下:
public static int uniquePaths(int m, int n) {
//定义二维数组
int[][] f = new int[m][n];
//起始条件
f[0][0] = 1;
//三种转移方程
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
//不在第一行和第一列,可以向左移,也可以下移
if (i > 0 && j > 0) {
f[i][j] = f[i - 1][j] + f[i][j - 1];
}
//j=0,第一列,下移
else if (i > 0) {
f[i][j] = f[i - 1][j];
}
//i=0,第一行,左移
else if (j > 0) {
f[i][j] = f[i][j - 1];
}
}
}
return f[m - 1][n - 1];
}
二.第63题 不同路径II
2.1题目要求
一个机器人位于一个 m x n 网格的左上角
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角
现在考虑网格中有障碍物。
那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1 和 0 来表示。
2.2解析
- 和上一题,几乎一样,动态规划定义和状态转移方程还是一样。不同的是多了一个障碍物。
- 把障碍物对应的位置f[i][j] 设置大小设置为0,说明没有路径。
- 判断起点是不是有障碍物,没有初始化为1,有的话,走不了为0。
- 在进行状态转移方程前,进行是否是障碍物的判断。不给障碍物复制,默认为0。
2.3编程求解
代码示例如下:
//改进思路,如果遇到障碍物了,把障碍物的f对应值设置为0,说明它不通
public static int uniquePathsWithObstacles(int[][] grid) {
int m = grid.length, n = grid[0].length;
int[][] f = new int[m][n];
//判断起始点有没有障碍,有障碍就没有路径了
f[0][0] = grid[0][0] == 1 ? 0 : 1;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
//只要没有不是障碍物就行
if (grid[i][j] != 1) {
if (i > 0 && j > 0) {
f[i][j] = f[i - 1][j] + f[i][j - 1];
} else if (i > 0) {
f[i][j] = f[i - 1][j];
} else if (j > 0) {
f[i][j] = f[i][j - 1];
}
}
}
}
return f[m - 1][n - 1];
}