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.
思路:
常见的错误解法就是每次走右边或下边数字中较小的那个,这样的贪婪算法获得的局部最优解不一定是全局最优解。
一个二维的 dp 数组,其中 dp[i][j] 表示到达当前位置的最小路径和。接下来找状态转移方程,因为到达当前位置 (i, j) 只有两种情况,要么从上方 (i-1, j) 过来,要么从左边 (i, j-1) 过来,我们选择 dp 值较小的那个路径,即比较 dp[i-1][j] 和 dp[i][j-1],将其中的较小值加上当前的数字 grid[i][j],就是当前位置的 dp 值了。但是,有些特殊情况要提前赋值,比如起点位置,直接赋值为 grid[0][0];第一行和第一列的值也要赋初值,其中第一行的位置只能从左边过来,第一列的位置从能从上面过来。然后再从 (1, 1) 的位置开始更新到右下角即可,难度不算大,代码如下:
dp[i][j] = grid[i][j] + min(dp[i - 1][j], dp[i][j - 1])
from typing import List
class Solution:
def minPathSum(self, grid: List[List[int]]) -> int:
# dp = [[grid[0][0]]*len(grid[0])]*len(grid) # 这种方法创建二位list不对
dp = [[grid[0][0] for i in range(len(grid[0]))] for j in range(len(grid))]
# print(dp)
for i in range(1,len(grid)):
dp[i][0] = dp[i-1][0] + grid[i][0]
# print(dp)
for j in range(1,len(grid[0])):
dp[0][j] = dp[0][j-1] + grid[0][j]
# print(dp[0][j])
for i in range(1,len(grid)):
for j in range(1,len(grid[0])):
dp[i][j] = min(dp[i-1][j],dp[i][j-1]) + grid[i][j]
return dp[len(grid)-1][len(grid[0])-1]
grid = [
[1,3,1],
[1,5,1],
[4,2,1]
]
solution = Solution()
solution.minPathSum(grid)
# 一维dp
from typing import List
class Solution:
def minPathSum(self, grid: List[List[int]]) -> int:
# dp = [[grid[0][0]]*len(grid[0])]*len(grid) # 这种方法创建二位list不对
dp = [100 for i in range(len(grid[0]))] # dp的初始值尽可能大
# print(dp)
dp[0] = 0
# print(dp)
for i in range(0,len(grid)):
for j in range(0,len(grid[0])):
if j == 0:
dp[j] += grid[i][j]
# print(dp)
else:
dp[j] = min(dp[j], dp[j - 1]) + grid[i][j]
# print(dp)
return dp[len(grid[0])-1]
grid = [
[1,3,1],
[1,5,1],
[4,2,1]
]
solution = Solution()
solution.minPathSum(grid)