?题目描述
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小
? Method 1: DP ,多一行一列,自下而上进行DP。time:O(mn),space:O(mn),和174题Dungeon Game很像
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
const vector<vector<int>> &g = grid;
int row = g.size();
int col = g[0].size();
vector<vector<int>> dp(row + 1, vector<int>(col + 1, INT32_MAX));
dp[row][col - 1] = dp[row - 1][col] = 0;
for (int i = row-1; i >= 0; --i) {
for (int j = col - 1; j >= 0; --j)
dp[i][j] = min(dp[i][j],min(dp[i+1][j],dp[i][j+1])+g[i][j]);
}
return dp[0][0];
}
};
? Method 2: DP ,和↑↑↑解法类似,不过↓↓↓是自上而下,从头到尾进行DP
![](https://i-blog.csdnimg.cn/blog_migrate/8d7987a897d01287a4ef594794ae2fa3.png)
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
const vector<vector<int>> &g = grid;
int row = g.size();
int col = g[0].size();
vector<vector<int>> dp(row, vector<int>(col, 0));
for (int i = 0; i < row; ++i) {
for (int j = 0; j < col; ++j) {
if (i == 0 && j == 0) dp[0][0] = g[0][0];
if (i == 0) { //对第一行进行特殊处理
dp[i][j] = g[i][j] + dp[i][j - 1];
}
else if (j == 0) { //对第一列进行特殊处理
dp[i][j] = g[i][j] + dp[i - 1][j];
}
else
dp[i][j] = g[i][j] + min(dp[i][j - 1], dp[i - 1][j]);
}
}
return dp[row-1][col-1];
}
};