一.题目原文
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.
中文解释:给定一张m x n的网格图,找到从左上角[0,0]到右下角[m-1][n-1]的一条路径,使得该路径经过的网格中的数字总和达到最小。
二.解决思路
因为是要找到最短路径,且起点和终点分别是网格的左上角和右下角,所以为了达到最短的路径长度,我们每一次在移动时,要么向右移动,要么向左移动。反过来,我们在到达任意一个网格时,要么是从它上边的网格到达,要么是从左边的网格到达。那么到达任意一个网格的最短路径长度都只取决于到达它的上边和左边的网格长度。
如果要得到到达终点网格的最短路径,我们只用求出该到达该网格上边和左边网格的最短路径即可。
分析到这里,我们可以很明显地看出,可以使用动态规划的思路来解决这个问题。下面给出动态规划算法的几个要素:
对于某个网格而言:
状态:到达该网格的最短路径长度。
状态转移方程:网格的最短路径长度 = min[上边网格最短路径长度, 左边网格最短路径长度] + 网格本身的开销。
特殊条件:如果是最左边的网格,则直接取上边网格的最短路径;反之亦然。(起点的最短路径长度直接为其本身开销)
从网格的起点终点遍历网格,按照上面的算法依次算出达到每一个网格的最短路径长度,则可以求得到达终点的最短路径长度。
三.代码实现
def minPathSum(grid):
m = len(grid)
n = len(grid[0])
row_length = [[] for i in range(n)]
path_length = [row_length[:] for i in range(m)]
for i in range(m):
for j in range(n):
len1 = (path_length[i][j-1] if j-1 >= 0 else -1)
len2 = (path_length[i-1][j] if i-1 >= 0 else -1)
if (len1 == -1):
path_length[i][j] = (0 if len2 == -1 else len2)
elif (len2 == -1):
path_length[i][j] = len1
else:
path_length[i][j] = min(len1, len2)
path_length[i][j] += grid[i][j]
return path_length[m-1][n-1]