64. Minimum Path Sum**(最小路径和)

64. Minimum Path Sum** (最小路径和)

https://leetcode.com/problems/minimum-path-sum/

题目描述

Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.

Note: You can only move either down or right at any point in time.

Example:

Input:
[
  [1,3,1],
  [1,5,1],
  [4,2,1]
]
Output: 7
Explanation: Because the path 1→3→1→1→1 minimizes the sum.

代码实现

64. Minimum Path Sum** 已经讲解过, 但这里重新补充更丰富的细节, 并且专门归类到 “动态规划” 目录中.

本题要求从左上角出发, 到达右下角时的最小路径和. 要写出状态转移方程, 首先要定义状态, 很明显, 转态是移动的位置, 由于 grid 是二维的, 因此我们定义二维 dp 数组, 其中 dp[i][j] 表示到达 grid[i][j] 时的最小路径和. 而要到达 grid[i][j], 要么从 grid[i][j] 的上方 (即 grid[i - 1][j]) 抵达, 要么从 grid[i][j] 的左边 (即 grid[i][j - 1]) 抵达, 于是我们可以很快写出状态转移方程:

dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j]

写出状态转移方程后, 下一步就是考虑初始情况以及边界问题.

为了方便处理边界情况, 令 dp 的大小为 (m + 1) x (n + 1), 并且初始化为 INT32_MAX, 但同时令 dp[0][1] = 0, 如下图:

相当于在外侧增加了一行和一列. 这样 dp[1][...] 以及 dp[...][1] 的边界情况能得到正确处理. 另外, 此时由于 dp[i + 1][j + 1] 表示的是 grid[i][j] 的状态, 那么对上面的状态转移方程做个简单的修改:

dp[i + 1][j + 1] = min(dp[i][j + 1], dp[i + 1][j]) + grid[i][j]

代码实现如下:

class Solution {
    
    
public:
    int minPathSum(vector<vector<int>>& grid) {
    
    
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT32_MAX));
        dp[0][1] = 0;
        for (int i = 0; i < m; ++ i) {
    
    
            for (int j = 0; j < n; ++ j) {
    
    
                dp[i + 1][j + 1] = min(dp[i][j + 1], dp[i + 1][j]) + grid[i][j];
            }
        }
        return dp[m][n];
    }
};

另外之前也写过一篇文章, 代码写法和思路如下:

扫描二维码关注公众号,回复: 14831715 查看本文章

动态规划. 使用 dp[i][j] 表示到达 grid[i][j] 所需要的最小 cost. (将 grid 中所有元素作为行走所需要的 cost). 为了方便做, 这里设置 dp 的大小为 (m + 1) x (n + 1). 边界情况的处理是在 for 循环中, 专门设置 i == 1 && j == 1 对应的 dp 值.

class Solution {
    
    
public:
    int minPathSum(vector<vector<int>>& grid) {
    
    
        if (grid.empty() || grid[0].empty()) return 0;
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT32_MAX));
        for (int i = 1; i <= m; ++ i) {
    
    
            for (int j = 1; j <= n; ++ j) {
    
    
                if (i == 1 && j == 1) dp[i][j] = grid[i - 1][j - 1];
                else dp[i][j] = grid[i - 1][j - 1] + std::min(dp[i - 1][j], dp[i][j - 1]);
            }
        }
        return dp[m][n];
    }
};

猜你喜欢

转载自blog.csdn.net/Eric_1993/article/details/114342596
今日推荐