给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入: [ [1,3,1], [1,5,1], [4,2,1] ] 输出: 7 解释: 因为路径 1→3→1→1→1 的总和最小。
思路:
要想知道最小路径,不把网格所有点都走一次是不可能知道的,单凭是右点大数值还是下点数值大选择移动路径是不对的,你永远不知道再前方会发生什么,不然示例路径第二步应该往下(1)而不是往右(3)走了。
但是都用搜索的方法把从起点到终点的路径都走一遍,那效率也太低了,要是地图再大一点,这么多条路,鬼知道什么时候能走完!
但是,无论经过一个网格点的路有多少条,只有一条路是最优,那我们还费什么劲,做无用功去搜索那些不是最优解的路呢?
将来总最优路径一定是从各个网格点最优路径里面选出来的。网格点m*n个,路径也就m*n条,比起搜索的路径不知道少到哪里去了。
求一条最优路径就够呛了,现在还要求m*n条最优路径,那怎么求啊?
由于只能往下和右走,对于某个网格,有两条分别从左和上来的路径要经过这个它(这两条路径都是到左点和上点的最优路径)
最优路径1 到该网格最小路径不言而喻,自然 min(路径1,路径2)+ 网格值
最优路径2 网格
那么怎么求路径1和路径2呢?把该网格的左和上像上面一样分析就行了啊
设dp[m][n]为起点到点(m,n)的最优路径,array[m][n]为点(m,n)的值
通过这波递归分析,可以得到:dp[m][n] = min ( dp[m-1][n] , dp[m][n-1]) + array[m][n]
为了节约空间,直接用array数组当做dp数组,用来存储最优路径
当然,对于上边界和左边界来说,到那些点的走法单一,没得选。
1 3 1 起点到每个点的最小路径和: 1 4 5
1 5 1 2 7 6
4 2 1 6 8 7
/* 上路径
↓
左路径 → 某点
当然 如果某点在列1,只有上到下
某点在排1,只有左到右
*/
class Solution {
public int minPathSum(int[][] grid) {
int m=grid.length,n=grid[0].length;
int dp[][]=new int[m][n];
dp[0][0]=grid[0][0];
for(int i=0;i<m;++i){
for(int j=0;j<n;++j){
if(j==0 && i>0){
dp[i][j]=grid[i][j]+dp[i-1][j];
}
if(i==0 && j>0){
dp[i][j]=grid[i][j]+dp[i][j-1];
}
if(i>0 && j>0){
dp[i][j]=Math.min(dp[i-1][j],dp[i][j-1])+grid[i][j];
}
}
}
return dp[m-1][n-1];
}
}