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.


典型的动态规划问题。

设dp[i][j]表示从左上角到grid[i][j]的最小路径和。那么dp[i][j] = grid[i][j] + min( dp[i-1][j], dp[i][j-1] );

下面的代码中,为了处理计算第一行和第一列的边界条件,我们令dp[i][j]表示从左上角到grid[i-1][j-1]的最小路径和,最后dp[m][n]是我们所求的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public:
    int minPathSum(vector<vector<int> > &grid) {
        int row = grid.size(),col;
        if(row == 0)return 0;
        else col = grid[0].size();
        vector<vector<int> >dp(row+1, vector<int>(col+1, INT_MAX));
        dp[0][1] = 0;
        for(int i = 1; i <= row; i++)
            for(int j = 1; j <= col; j++)
                dp[i][j] = grid[i-1][j-1] + min(dp[i][j-1], dp[i-1][j]);
        return dp[row][col];
    }
};

注意到上面的代码中dp[i][j] 只和上一行的dp[i-1][j]和上一列的dp[i][j-1]有关,因此可以优化空间为O(n)(准确来讲空间复杂度可以是O(min(row,col

)))                          本文地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public:
    int minPathSum(vector<vector<int> > &grid) {
        int row = grid.size(),col;
        if(row == 0)return 0;
        else col = grid[0].size();
        vector<int >dp(col+1, INT_MAX);
        dp[1] = 0;
        for(int i = 1; i <= row; i++)
            for(int j = 1; j <= col; j++)
                dp[j] = grid[i-1][j-1] + min(dp[j], dp[j-1]);
        return dp[col];
    }
};


问题扩展

最大路径和只需要把上面的递推公式中的min换成max。

现在有个问题,如果两个人同时从左上角出发,目的地是右下角,两个人的路线不能相交(即除了出发点和终点外,两个人不同通过同一个格子),使得两条路径的和最大。(这和一个人先从左上角到右下角,再回到左上角是相同的问题)。

这是双线程动态规划问题:假设网格为grid,dp[k][i][j]表示两个人都走了k步,第一个人向右走了i步,第二个人向右走了j步 时的最大路径和(只需要三个变量就可以定位出两个人的位置grid[k-i][i-1] 、 grid[k-j][j-1]),那么

dp[k][i][j] = max(dp[k-1][i-1][j-1], dp[k-1][i][j], dp[k-1][i-1][j], dp[k-1][i][j-1]) + grid[k-i][i-1] + grid[k-j][j-1]  (我们假设在起始位置时就已经走了一步)

这个方程的意思是从第k-1步到第k步,可以两个人都向右走、都向下走、第一个向下第二个向右、第一个向右第二个向下,这四种走法中选择上一步中路径和最大的。

由于要保证两条路线不能相交,即两个人走的过程中,有一个人向右走的步数永远大于另一个人向右走的步数,我们不妨设第二个人向右走的步数较大,即dp[k][i][j]中j > i才是有效的状态。走到终点的步数为:网格的行数+网格的列数-1

需要注意的是:当走了k步时,某个人向右走的步数必须 > k - 网格的行数,如果向右走的步数 <= k-行数,那么向下走的步数 = k-向右走的步数 >= 行数,此时超出了网格的范围。由于我们假设了 j > i,因此只要保证 i > k-网格行数即可。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int max2PathSum(vector<vector<int> > grid)
{
    int row = grid.size(), col = grid[0].size();
    vector<vector<vector<int> > > dp(row+col, vector<vector<int> >(col+1, vector<int>(col+1, 0)));
    for(int step = 2; step <= row+col-2; step++)
        for(int i = max(1, step-row+1); i <= step && i <= col; i++)
            for(int j = i+1; j <= step && j <= col; j++)
            {
                 
                dp[step][i][j] = max(max(dp[step-1][i][j], dp[step-1][i-1][j-1]), max(dp[step-1][i-1][j], dp[step-1][i][j-1]));
                dp[step][i][j] += (grid[step-i][i-1] + grid[step-j][j-1]);
            }
    return dp[row+col-2][col-1][col] + 2*grid[row-1][col-1] + 2*grid[0][0];
}

我们最终的目标是dp[row+col-1][col][col] = max{dp[row+col-2][col-1][col-1], dp[row+col-2][col][col], dp[row+col-2][col-1][col], dp[row+col-2][col][col-1]} + 2*grid[row-1][col-1]

由于dp[row+col-2][col-1][col-1], dp[row+col-2][col][col], dp[row+col-2][col][col-1]都是无效的状态(dp[k][i][j]中j > i才是有效的状态),

所以dp[row+col-1][col][col]  = dp[row+col-2][col-1][col] + 2*grid[row-1][col-1],代码中最后结果还加上了所在起点的的网格值。

由以上可知,循环中最多只需要求到了dp[row+col-2][][]。

nyoj中 传纸条(一)就是这个问题,可以在这一题中测试上述函数的正确性,测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main()
{
    int n;
    scanf("%d",&n);
    for(int i = 1; i <= n; i++)
    {
        int row, col;
        scanf("%d%d", &row, &col);
        vector<vector<int> >grid(row, vector<int>(col));
        for(int a = 0; a < row; a++)
            for(int b = 0; b < col; b++)
                scanf("%d", &grid[a][b]);
        printf("%d\n", max2PathSum(grid));
    }
    return 0;
}

这个问题还可以使用最小费用流来解决,具体可以参考here

本文转自tenos博客园博客,原文链接:http://www.cnblogs.com/TenosDoIt/p/3774804.html,如需转载请自行联系原作者

LeetCode:Minimum Path Sum(网格最大路径和)相关推荐

  1. [leetcode] Minimum Path Sum

    Minimum Path Sum Given a m x n grid filled with non-negative numbers, find a path from top left to b ...

  2. LeetCode Minimum Path Sum(动态规划)

     Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right wh ...

  3. leetcode 437. Path Sum III | 437. 路径总和 III(DFS,前缀和)

    题目 https://leetcode.com/problems/path-sum-iii/ 题解 DFS+前缀和问题,注意节点可能为 0 的情况(也是因此发现应该用 HashMap 记录前缀和的个数 ...

  4. 【DP】LeetCode 64. Minimum Path Sum

    LeetCode 64. Minimum Path Sum Solution1:标准的动态规划题目 class Solution { public:int minPathSum(vector<v ...

  5. 【leetcode】Minimum Path Sum

    Minimum Path Sum Given a m x n grid filled with non-negative numbers, find a path from top left to b ...

  6. 63. Unique Paths II and 64. Minimum Path Sum

    文章目录 1 63 Unique Paths II 1.1 题目描述 1.2 动态规划解决 2 64. Minimum Path Sum 2.1 题目理解 2.2 动态规划 这一遍刷dp的题目就很轻松 ...

  7. [勇者闯LeetCode] 112. Path Sum

    [勇者闯LeetCode] 112. Path Sum Description Given a binary tree and a sum, determine if the tree has a r ...

  8. leetcode 112. Path Sum, 113. Path Sum II | 112,113. 路径总和 I, II(Java)

    题目 https://leetcode.com/problems/path-sum/ https://leetcode.com/problems/path-sum-ii/ 题解 简单的遍历二叉树,不解 ...

  9. [LeetCode]113.Path Sum II

    [题目] Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the giv ...

最新文章

  1. $.post请求的参数在后台代码中得到为null_996难得休息,小伙打开steam网页看了一款游戏,输入密码后却习惯性按了F12研究起了JS代码...
  2. 那天有个小孩跟我说LINQ(五)转载
  3. the value of esp was not properly saved
  4. 与其他Javascript类库冲突解决方案
  5. python一维列表的定义_数据结构-Python 列表(List)
  6. 不用去验血,对照这张表,就能知道自己缺啥!千万收藏好!
  7. Win10系统电脑不会一键还原系统怎么解决
  8. 图解集合6:LinkedHashMap
  9. Linux系统编程 -- 死锁
  10. DevExpress v15.1:Reporting控件功能增强(二)
  11. c语言——约瑟夫环(数组)
  12. RGB灯串24键红外遥控控制器芯片 SOP-8氛围灯小夜灯单片机芯片方案开发
  13. java开发运行环境的安装步骤_配置java开发运行环境的步骤
  14. 多重中介效应的示例数据(内附STATA代码)
  15. 最新团长头像制作小程序源码+云开发的/支持流量主
  16. 9个关键词,2万字漫谈元宇宙
  17. 那些年震撼我们心灵的音乐
  18. 电脑只能上QQ,不能上网浏览网站怎么解决
  19. java 导入导出excel表格
  20. yandex注册验证码怎么填_注册163邮箱格式怎么填?163电子邮件注册格式

热门文章

  1. 七月时忙碌而充实的_如何减少忙碌而更有效
  2. 梳理了一下前端面试必考知识点
  3. Android 应用安全性改进: 全面助力打造 零漏洞 应用
  4. webpack4.0配置记录(2)
  5. cookie与session详解
  6. 刺猬文│从启动方式来看播客链的运行机制—设置验证者
  7. Using Python with Oracle
  8. 配置SSH非管理员用户登录
  9. 新服务器安装和配置zabbix的playbook
  10. MFC载入JPG图片