题目链接:点击查看
题目描述:
给定一个 m × n 大小的非负整数矩阵,求从左上角开始到右下角结束的、经过的数字的和最小的路径。每次只能向右或者向下移动。
输入输出:
输入:grid = [[1,3,1],[1,5,1],[4,2,1]] 输出:7
输入:grid = [[1,2,3],[4,5,6]] 输出:12
题目分析:
我们可以定义一个同样是二维的 dp 数组,其中 dp[i][j] 表示从左上角开始到 (i, j) 位置的最优路径的数字和。因为每次只能向下或者向右移动,我们可以很容易得到状态转移方程 dp[i][j]=min(dp[i-1][j], dp[i][j-1]) + grid[i][j],其中 grid 表示原数组。
代码:
int minPathSum(vector<vector<int>>&grid)
{
int m=grid.size(),n=grid[0].size();
vector<vector<int>>dp(m,vector<int>(n,0));
for(int i=0;i<m;++i)
{
for(int j=0;j<n;++j)
{
if(i==0&&j==0)
{
dp[i][j]=grid[i][j];
}
else if(i==0)
{
dp[i][j]=dp[i][j-1]+grid[i][j];
}
else if(j==0)
{
dp[i][j]=dp[i-1][j]+grid[i][j];
}
else
{
dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j];
}
}
}
return dp[m-1][n-1];
}
空间压缩:
因为 dp 矩阵的每一个值只和左边和上面的值相关,我们可以使用空间压缩将 dp 数组压缩为一维。对于第 i 行,在遍历到第 j 列的时候,因为第 j-1 列已经更新过了,所以 dp[j-1] 代表 dp[i][j-1]的值;而 dp[j] 待更新,当前存储的值是在第 i-1 行的时候计算的,
所以代表 dp[i-1][j] 的值。
代码:
int minPathSum(vector<vector<int>>&grid)
{
int m=grid.size(),n=grid[0].size();
vector<int>dp(n,0);
for(int i=0;i<m;++i)
{
for(int j=0;j<n;++j)
{
if(i==0&&j==0)
{
dp[j]=grid[i][j];
}
else if(i==0)
{
dp[j]=dp[j-1]+grid[i][j];
}
else if(j==0)
{
dp[j]=dp[j-1]+grid[i][j];
}
else
{
dp[j]=min(dp[j],dp[j-1]+grid[i][j]);
}
}
}
return dp[n-1];
}