最小路径和
64. 最小路径和
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
动态规划
设f(m,n)为左上角到点(m,n)的最小路径和
则状态转移方程
dp(m,n)=grid(m,n) + min{dp(m,n-1),dp(m-1,n)}, 当m>0,n>0
base case:m=0或n=0时,即二维dp表格的首行,首列
dp(0,0)=grid(0,0);
dp(0,n)=dp(0,n-1)+grid(0,n);n>=1时
dp(m,0)=dp(m-1,0)+grid(m,0);m>=1时
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
if(grid.empty()) return 0;
//base case
int row=grid.size();
int col=grid[0].size();
vector<vector<int>> dp(row,vector<int>(col,0));
//首行
dp[0][0]=grid[0][0];
for(int i=0;i<col-1;i++)
dp[0][i+1]=dp[0][i]+grid[0][i+1];
//首列
for(int j=0;j<row-1;j++)
dp[j+1][0]=dp[j][0]+grid[j+1][0];
for(int m=1;m<row;m++){
for(int n=1;n<col;n++){
dp[m][n]=min(dp[m][n-1],dp[m-1][n])+grid[m][n];
}
}
return dp[row-1][col-1];
}
};
带备忘录的递归
class Solution{
int helper(vector<vector<int>>& grid,vector<vector<int>>& memory,int row,int col){
if(row<0||col<0) return INT_MAX;//用于首行,首列的边界情况
if(memory[row][col]!=-1) return memory[row][col];
memory[row][col]=min(helper(grid,memory,row,col-1),helper(grid,memory,row-1,col))+grid[row][col];
return memory[row][col];
}
public:
int minPathSum(vector<vector<int>>& grid){
int row=grid.size();
int col=grid[0].size();
//备忘录
vector<vector<int>> memory(row,vector<int>(col,-1));
memory[0][0]=grid[0][0];
return helper(grid,memory,row-1,col-1);
}
};