64. Minimum Path Sum** (最小路径和)
https://leetcode.com/problems/minimum-path-sum/
题目描述
Given a m x n
grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.
Note: You can only move either down or right at any point in time.
Example:
Input:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
Output: 7
Explanation: Because the path 1→3→1→1→1 minimizes the sum.
代码实现
在 64. Minimum Path Sum** 已经讲解过, 但这里重新补充更丰富的细节, 并且专门归类到 “动态规划” 目录中.
本题要求从左上角出发, 到达右下角时的最小路径和. 要写出状态转移方程, 首先要定义状态, 很明显, 转态是移动的位置, 由于 grid
是二维的, 因此我们定义二维 dp
数组, 其中 dp[i][j]
表示到达 grid[i][j]
时的最小路径和. 而要到达 grid[i][j]
, 要么从 grid[i][j]
的上方 (即 grid[i - 1][j]
) 抵达, 要么从 grid[i][j]
的左边 (即 grid[i][j - 1]
) 抵达, 于是我们可以很快写出状态转移方程:
dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j]
写出状态转移方程后, 下一步就是考虑初始情况以及边界问题.
为了方便处理边界情况, 令 dp
的大小为 (m + 1) x (n + 1)
, 并且初始化为 INT32_MAX
, 但同时令 dp[0][1] = 0
, 如下图:
相当于在外侧增加了一行和一列. 这样 dp[1][...]
以及 dp[...][1]
的边界情况能得到正确处理. 另外, 此时由于 dp[i + 1][j + 1]
表示的是 grid[i][j]
的状态, 那么对上面的状态转移方程做个简单的修改:
dp[i + 1][j + 1] = min(dp[i][j + 1], dp[i + 1][j]) + grid[i][j]
代码实现如下:
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size();
vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT32_MAX));
dp[0][1] = 0;
for (int i = 0; i < m; ++ i) {
for (int j = 0; j < n; ++ j) {
dp[i + 1][j + 1] = min(dp[i][j + 1], dp[i + 1][j]) + grid[i][j];
}
}
return dp[m][n];
}
};
另外之前也写过一篇文章, 代码写法和思路如下:
动态规划. 使用 dp[i][j]
表示到达 grid[i][j]
所需要的最小 cost. (将 grid
中所有元素作为行走所需要的 cost). 为了方便做, 这里设置 dp
的大小为 (m + 1) x (n + 1)
. 边界情况的处理是在 for
循环中, 专门设置 i == 1 && j == 1
对应的 dp
值.
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
if (grid.empty() || grid[0].empty()) return 0;
int m = grid.size(), n = grid[0].size();
vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT32_MAX));
for (int i = 1; i <= m; ++ i) {
for (int j = 1; j <= n; ++ j) {
if (i == 1 && j == 1) dp[i][j] = grid[i - 1][j - 1];
else dp[i][j] = grid[i - 1][j - 1] + std::min(dp[i - 1][j], dp[i][j - 1]);
}
}
return dp[m][n];
}
};