1594. 矩阵的最大非负积(Rating 1807)
1594. 矩阵的最大非负积(Rating 1807)
以下内容偏向于记录个人练习过程及思考,非常规题解内容
题目
思路
对于二维网格从左上走到右下的问题,大概率是动态规划问题。
因为每个格子的状态只与其上面和左面的格子状态有关。
因为负数*负数也可以得到正数,所以我们需要记录路径上乘积最小的负数,以便在后面再遇到负数时有机会得到较大的正数。
因此考虑
对每个格子维护两个值,即最小值和最大值。
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
MOD = 10 ** 9 + 7
class Solution:
def maxProductPath(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
# dp[0][i][j] 记录经过第(i, j)个格子可以获得的最小值
# dp[1][i][j] 记录经过第(i, j)个格子可以获得的最大值
dp = [[[0 for _ in range(n)] for _ in range(m)] for _ in range(2)]
dp[0][0][0] = grid[0][0] # 初始化第(0, 0)个格子
dp[1][0][0] = grid[0][0] # 初始化第(0, 0)个格子
for i in range(1, m): # 遍历所有行,初始化第0列,该列的乘积结果只与上面的乘积结果有关
dp[0][i][0] = dp[0][i - 1][0] * grid[i][0]
dp[1][i][0] = dp[0][i][0]
for i in range(1, n): # 遍历所有列,初始化第0行,该行的乘积结果只与左面的乘积结果有关
dp[0][0][i] = dp[0][0][i - 1] * grid[0][i]
dp[1][0][i] = dp[0][0][i]
for i in range(1, m): # 遍历所有行
for j in range(1, n): # 遍历所有列
dp[0][i][j] = min( # 第(i, j)个格子的最小值可能来自
dp[0][i - 1][j] * grid[i][j], # 上面格子的最小值 与 当前值相乘
dp[1][i - 1][j] * grid[i][j], # 上面格子的最大值 与 当前值相乘
dp[0][i][j - 1] * grid[i][j], # 左面格子的最小值 与 当前值相乘
dp[1][i][j - 1] * grid[i][j], # 左面格子的最大值 与 当前值相乘
)
dp[1][i][j] = max( # 同上
dp[0][i - 1][j] * grid[i][j],
dp[1][i - 1][j] * grid[i][j],
dp[0][i][j - 1] * grid[i][j],
dp[1][i][j - 1] * grid[i][j],
)
return -1 if dp[1][-1][-1] < 0 else dp[1][-1][-1] % MOD # 按照题目规则返回答案
本文由作者按照 CC BY 4.0 进行授权