本文共 2365 字,大约阅读时间需要 7 分钟。
为了解决这个问题,我们需要找到从矩阵左上角到右下角的所有路径中,具有最大非负积的路径。由于路径只能向右或向下移动,这是一个典型的动态规划问题。
问题分析:路径只能向右或向下移动,因此我们可以使用动态规划来记录每个点的最大和最小乘积。最大乘积可能由当前点的正数与之前的最大乘积相乘得到,而最小乘积可能由当前点的负数与之前的最小乘积相乘得到。这样可以确保我们在后续步骤中考虑所有可能的正乘积情况。
状态定义:使用两个二维数组max_dp和min_dp,分别记录到达每个点时的最大和最小乘积。
初始化:起点(0,0)的值直接赋值给max_dp和min_dp。
填充边缘:处理第一行和第一列的值,因为它们只能从左边或上边移动过来。
动态规划转移:对于每个点,计算其max_dp和min_dp值,考虑从左边和上边移动过来的可能性,并结合当前点的值进行计算。
结果判断:到达终点后,检查最大乘积是否为非负数,并返回结果。
from typing import ListMOD = 10**9 + 7class Solution: def maxProductPath(self, grid: List[List[int]]) -> int: rows = len(grid) if rows == 0: return -1 cols = len(grid[0]) if cols == 0: return -1 # 初始化max_dp和min_dp矩阵 max_dp = [[0] * cols for _ in range(rows)] min_dp = [[0] * cols for _ in range(rows)] # 起点 max_dp[0][0] = min_dp[0][0] = grid[0][0] # 填充第一行 for j in range(1, cols): max_dp[0][j] = max_dp[0][j-1] * grid[0][j] min_dp[0][j] = min_dp[0][j-1] * grid[0][j] # 填充第一列 for i in range(1, rows): max_dp[i][0] = max_dp[i-1][0] * grid[i][0] min_dp[i][0] = min_dp[i-1][0] * grid[i][0] # 填充剩余部分 for i in range(1, rows): for j in range(1, cols): # 计算当前位置可能的max和min candidates_max = [ max_dp[i-1][j] * grid[i][j], max_dp[i][j-1] * grid[i][j], min_dp[i-1][j] * grid[i][j], min_dp[i][j-1] * grid[i][j] ] current_max = max(candidates_max) candidates_min = [ max_dp[i-1][j] * grid[i][j], max_dp[i][j-1] * grid[i][j], min_dp[i-1][j] * grid[i][j], min_dp[i][j-1] * grid[i][j] ] current_min = min(candidates_min) max_dp[i][j] = current_max min_dp[i][j] = current_min # 检查终点是否非负 final_max = max_dp[rows-1][cols-1] if final_max >= 0: return final_max % MOD else: return -1
初始化:创建max_dp和min_dp矩阵,起点初始化为grid[0][0]。
填充边缘:处理第一行和第一列的值,使用当前点的值与前一个点的值相乘。
动态规划转移:对于每个点,计算其max_dp和min_dp值,考虑从左边和上边移动过来的可能性,并结合当前点的值进行计算。
结果判断:到达终点后,检查最大乘积是否为非负数,并返回结果。结果需要对10^9 + 7取模,若最大乘积为负数则返回-1。
转载地址:http://nmgr.baihongyu.com/