动态规划-最短路径和

给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
规定每次只能向下或者向右移动一步。

输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。

动态规划:
1、由于路径只能向右或者向下,因此第一行和第一列的路径是唯一的,只需要把对应的元素值相加即可。
2、对于不是第一行和第一列的元素,可以从上方的元素向下移动或者左方的元素向右移动到达,到达该元素位置的最小路径等于其上方或者左方的最小值加上当前元素的值。
3、创建二维数组 dp,与原始网格的大小相同,dp[i][j] 表示从左上角出发到 (i,j) 位置的最小路径和。显然,dp[0][0]=grid[0][0]。对于 dp 中的其余元素,通过以下状态转移方程计算元素值。

  • 当 i>0 且 j=0 时,dp[i][0] = dp[i-1][0] + grid[i][0]。
  • 当 i=0 且 j>0 时,dp[0][j] = dp[0][j-1] + grid[0][j]。
  • 当 i>0 且 j>0 时,dp[i][j] = min(dp[i−1][j],dp[i][j−1]) + grid[i][j]。
#define ROW 3
#define COL 3
int minPathSum(vector<vector<int> >& matrix) 
{
    const int row = matrix.size();
    const int col = matrix[0].size();
    int dp[ROW][COL];  //dp[i][j]表示,从[0,0]开始,走到[i,j]的最小路径和
    //初始化第一列和第一行
    dp[0][0] = matrix[0][0];
    for (int i = 1; i < row; ++i)
        dp[i][0] = dp[i - 1][0] + matrix[i][0];
    for (int i = 1; i < col; ++i)
        dp[0][i] = dp[0][i - 1] + matrix[0][i];
    //除了第一行第一列之外的其他元素
    for (int i = 1; i < row; ++i)
        for (int j = 1; j < col; ++j)
            dp[i][j] = min(dp[i][j - 1], dp[i - 1][j]) + matrix[i][j];
    return dp[row - 1][col - 1];
}

复杂度:
时间复杂度:O(m*n),其中 m 和 n 分别是网格的行数和列数。需要对整个网格遍历一次,计算 dp 的每个元素的值。

空间复杂度:O(m*n),其中 m 和 n 分别是网格的行数和列数。创建一个二维数组 dp,和网格大小相同。
注:空间复杂度可以优化,例如每次只存储上一行的 dp 值,则可以将空间复杂度优化到 O(n)。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vegetablesssss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值