题目链接

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]是我们所求的结果

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

)))                          本文地址

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-网格行数即可。

代码如下:

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中 传纸条(一)就是这个问题,可以在这一题中测试上述函数的正确性,测试代码如下:

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

 

 

【版权声明】转载请注明出处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. 动态规划小结 - 二维动态规划 - 时间复杂度 O(n*n)的棋盘型,题 [LeetCode] Minimum Path Sum,Unique Paths II,Edit Distance

    引言 二维动态规划中最常见的是棋盘型二维动态规划. 即 func(i, j) 往往只和 func(i-1, j-1), func(i-1, j) 以及 func(i, j-1) 有关 这种情况下,时间 ...

  3. [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 given su ...

  4. [LeetCode] 112. Path Sum 二叉树的路径和

    Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all ...

  5. LeetCode 437. Path Sum III (路径之和之三)

    You are given a binary tree in which each node contains an integer value. Find the number of paths t ...

  6. [LeetCode] Minimum Path Sum 最小路径和

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

  7. LeetCode OJ:Minimum Path Sum(最小路径和)

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

  8. Leetcode Minimum Path Sum

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

  9. LeetCode 112. Path Sum (二叉树路径之和)

    Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all ...

随机推荐

  1. 最短路算法 (bellman-Ford算法)

    贝尔曼-福特算法与迪科斯彻算法类似,都以松弛操作为基础,即估计的最短路径值渐渐地被更加准确的值替代,直至得到最优解.在两个算法中,计算时每个边之间的估计距离值都比真实值大,并且被新找到路径的最小长度替 ...

  2. String reorder

    本问题出自:微软2014实习生及秋令营技术类职位在线测试 (Microsoft Online Test for Core Technical Positions) Description For th ...

  3. submit(提交)按钮

    为form添加一个submit(提交)按钮,点击这个按钮,表单中的数据将会被发送到通过action属性指定的地址上. 下面是submit按钮的例子: <button type="sub ...

  4. p7 struct and union

    struct  StudentRec           //①声明结构体类型StudentRec{        char StuNum[20];        //②定义结构体的成员变量      ...

  5. 一步一步搭建客服系统 (4) 客户列表 - JS($.ajax)调用WCF 遇到的各种坑

    本文以一个生成.获取“客户列表”的demo来介绍如何用js调用wcf,以及遇到的各种问题. 1 创建WCF服务 1.1 定义接口 创建一个接口,指定用json的格式:   [ServiceContra ...

  6. 用c#开发微信(3)基于Senparc.Weixin框架的接收普通消息处理 (源码下载)

    本文讲述使用Senparc.Weixin框架来快速处理各种接收的普通消息.这里的消息指的是传统的微信公众平台消息交互,微信用户向公众号发送消息后,公众号回复消息给微信用户.包括以下7种类型: 1 文本 ...

  7. Dynamic CRM 2013学习笔记(二十八)用JS动态设置字段的change事件、必填、禁用以及可见

    我们知道通过界面设置字段的change事件,是否是必填,是否可见非常容易.但有时我们需要动态地根据某些条件来设置,这时有需要通过js来动态地控制了. 下面分别介绍如何用js来动态设置.   一.动态设 ...

  8. GoDaddy自动续费信用卡被扣款后的退款方法

    今天突然收到信用卡被GoDaddy捐款的通知,上GoDaddy网站上一看,是去年购买后来没有使用的一个CA证书被自动续费了.原来在GoDaddy购买的CA证书默认是每年自动续费的,这是一个大坑啊! 当 ...

  9. 最新 Windows 10 应用项目模板发布

    以下是最新的Visual Studio 2015 Windows 10 应用程序模板. Windows 10中几乎所有的官方应用都遵循这样一个设计模板:在左上方有一个所谓的导航栏.点击该导航按钮,左侧 ...

  10. Lingo 做线性规划 - Revenue Management

    Reference: <An Introduction to Management Science Quantitative Approaches to Decision Making, Rev ...