1289. 下降路径最小和 II

给你一个整数方阵 arr ,定义「非零偏移下降路径」为:从 arr 数组中的每一行选择一个数字,且按顺序选出来的数字中,相邻数字不在原数组的同一列。
请你返回非零偏移下降路径数字和的最小值。
示例 1:
输入:arr = [[1,2,3],[4,5,6],[7,8,9]] 输出:13 解释: 所有非零偏移下降路径包括: [1,5,9], [1,5,7], [1,6,7], [1,6,8], [2,4,8], [2,4,9], [2,6,7], [2,6,8], [3,4,8], [3,4,9], [3,5,7], [3,5,9] 下降路径中数字和最小的是 [1,5,7] ,所以答案是 13 。
提示:
  • 1 <= arr.length == arr[i].length <= 200
  • 99 <= arr[i][j] <= 99
#法1 动态规划
思路
依旧是第一类基本型:时间序列型题目。
按照套路,先定义状态如下:
dp[i][j] : 到 i 行 时,选择 j列 的最小值。j为状态,i为轮数(天数)
状态jlen(arr[0]) 种状态
天数 ilen(arr)
状态转移如下:
notion imagenotion image
对于 第 i 天的状态j ,除了不能选第i-1天的状态j,其余状态都可以选
for j in range(len(dp[0])): # 选择 前一轮 除j外最便宜的颜料 cost = min([dp[i-1][k] for k in range(len(dp[0])) if k != j]) dp[i][j] = min(dp[i][j], grid[i][j]+cost)
题解
class Solution: def minFallingPathSum(self, grid: List[List[int]]) -> int: dp = [[float('inf')]*len(grid[0]) for _ in range(len(grid))] dp[0] = grid[0][:] print(dp) for i in range(1, len(dp)): for j in range(len(dp[0])): # 选择 前一轮 除j外最便宜的颜料 cost = min([dp[i-1][k] for k in range(len(dp[0])) if k != j]) dp[i][j] = min(dp[i][j], grid[i][j]+cost) return min(dp[-1])
优雅写法
class Solution: def minFallingPathSum(self, grid: List[List[int]]) -> int: m, n = len(grid), len(grid[0]) dp = [[0] * n for _ in range(m)] dp[0] = grid[0][:] for i in range(1, m): for j in range(0, n): dp[i][j] = grid[i][j] + min(*dp[i-1][0:j], *dp[i-1][j+1:]) return min(dp[-1])
优化:因为之和之前一个状态相关,所以只需要O(n)的复杂度
class Solution: def minFallingPathSum(self, grid: List[List[int]]) -> int: dp = grid[0][:] for i in range(1, len(grid)): dp_ = [0 for _ in grid[0]] for j in range(0, len(grid)): dp_[j] = min(dp[:j] + dp[j+1:]) + grid[i][j] dp = dp_ return min(dp)