1. 题目链接:64. 最小路径和
2. 题目描述:
给定一个包含非负整数的
*m* x *n*
网格grid
,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。**说明:**每次只能向下或者向右移动一步。
示例 1:
输入:grid = [[1,3,1],[1,5,1],[4,2,1]] 输出:7 解释:因为路径 1→3→1→1→1 的总和最小。
示例 2:
输入:grid = [[1,2,3],[4,5,6]] 输出:12
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 200
0 <= grid[i][j] <= 200
3. 解法(动态规划)
3.1 算法思路:
3.1.1 状态表示:
dp[i][j]
表示:到达[i,j]
位置处,最小路径和是多少
3.1.2 状态转移:
如果 dp[i][j]
表示到达 [i,j]
位置处的最小路径和,那么到达[i,j]
位置之前的一小步,有两种情况:
- 从
[i-1,j]
向下走一步,转移到[i,j]
位置 - 从
[i,j-1]
向右走一步,转移到[i,j]
位置
dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i-1][j-1]
3.1.3 初始化:
可以在最前面加上一个辅助结点,帮助我们初始化。使用这种技巧要注意两个点:
-
辅助结点里面的值要保证后续填表是正确的
-
下标的映射关系
-
在本题中,添加一行和添加一列后,所有位置的值可以初始化为无穷大,然后让
dp[0][1]=d[1][0]=0
即可
3.1.4 填表顺序:
根据状态转移方程的推导来看,填表的顺序就是从上往下填每一行,每一行从左往右
3.1.5返回值:
根据状态表示,我们要返回的结果是dp[m][n]
3.2 C++算法代码:
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
int m=grid.size();
int n=grid[0].size();
//创建dp表
vector<vector<int>>dp(m+1,vector<int>(n+1,INT_MAX));
//初始化
dp[0][1]=0,dp[1][0]=0;
//填表
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i-1][j-1];
}
}
//返回结果
return dp[m][n];
}
};