leetcode 1594. 矩阵的最大非负积 中等

给你一个大小为 m x n 的矩阵 grid 。最初,你位于左上角 (0, 0) ,每一步,你可以在矩阵中 向右向下 移动。

在从左上角 (0, 0) 开始到右下角 (m - 1, n - 1) 结束的所有路径中,找出具有 最大非负积 的路径。路径的积是沿路径访问的单元格中所有整数的乘积。

返回 最大非负积 对**109 + 7** 取余 的结果。如果最大积为 负数 ,则返回-1

**注意,**取余是在得到最大积之后执行的。

示例 1:

复制代码
输入:grid = [[-1,-2,-3],[-2,-3,-3],[-3,-3,-2]]
输出:-1
解释:从 (0, 0) 到 (2, 2) 的路径中无法得到非负积,所以返回 -1 。

示例 2:

复制代码
输入:grid = [[1,-2,1],[1,-2,1],[3,-4,1]]
输出:8
解释:最大非负积对应的路径如图所示 (1 * 1 * -2 * -4 * 1 = 8)

示例 3:

复制代码
输入:grid = [[1,3],[0,-4]]
输出:0
解释:最大非负积对应的路径如图所示 (1 * 0 * -4 = 0)

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 15
  • -4 <= grid[i][j] <= 4

分析:由于两个负数相乘可以得到正数,因此除了求最大乘积,还要求最小乘积。令 dp[i][j].mini 代表从左上角(0,0)走到(i,j)的路径最小乘积,dp[i][j].maxn 代表从左上角(0,0)走到(i,j)的路径最大乘积。想要走到点(i,j),要么从上面(i-1,j)走来,要么从左边(i,j-1)走来,可以得到两个计算式:

cpp 复制代码
dp[i][j].mini=min(min(dp[i-1][j].mini*grid[i][j],dp[i-1][j].maxn*grid[i][j]),min(dp[i][j-1].mini*grid[i][j],dp[i][j-1].maxn*grid[i][j]));
dp[i][j].maxn=max(max(dp[i-1][j].mini*grid[i][j],dp[i-1][j].maxn*grid[i][j]),max(dp[i][j-1].mini*grid[i][j],dp[i][j-1].maxn*grid[i][j]));

最后答案就是 dp[m-1][n-1].mini 和 dp[m-1][n-1].maxn 的最大值对 1e9+7 取模的值。注意取余是在得到最大积之后执行的,因此中间值需要用 long long 避免溢出。

cpp 复制代码
long long min(long long a,long long b)
{
    return a>b?b:a;
}
long long max(long long a,long long b)
{
    return a>b?a:b;
}
typedef struct node
{
    long long mini,maxn;
}node;
int maxProductPath(int** grid, int gridSize, int* gridColSize) {
    int m=gridSize,n=*gridColSize;
    long long mod=1e9+7;
    node dp[m+5][n+5];
    dp[0][0].mini=dp[0][0].maxn=grid[0][0]*1LL;
    for(int i=1;i<m;++i)
        dp[i][0].mini=dp[i][0].maxn=1LL*dp[i-1][0].mini*grid[i][0];
    for(int j=1;j<n;++j)
        dp[0][j].mini=dp[0][j].maxn=1LL*dp[0][j-1].mini*grid[0][j];
        
    for(int i=1;i<m;++i)
    {
        for(int j=1;j<n;++j)
        {
            dp[i][j].mini=min(min(dp[i-1][j].mini*grid[i][j],dp[i-1][j].maxn*grid[i][j]),min(dp[i][j-1].mini*grid[i][j],dp[i][j-1].maxn*grid[i][j]));
            dp[i][j].maxn=max(max(dp[i-1][j].mini*grid[i][j],dp[i-1][j].maxn*grid[i][j]),max(dp[i][j-1].mini*grid[i][j],dp[i][j-1].maxn*grid[i][j]));
        }
    }

    return (int)(max(max(dp[m-1][n-1].mini,dp[m-1][n-1].maxn),-1)%mod);
}
相关推荐
重生之我是Java开发战士2 小时前
【广度优先搜索】队列:N叉树的层序遍历,二叉树的锯齿形层序遍历,二叉树的最大宽度,在每个树行中找最大值
数据结构·算法·leetcode·广度优先
灰色小旋风2 小时前
力扣20有效的括号(C++)
c++·算法·leetcode·职场和发展
逆境不可逃2 小时前
LeetCode 热题 100 之 160. 相交链表 206. 反转链表 234. 回文链表 141. 环形链表 142. 环形链表 II
算法·leetcode·链表
灰色小旋风3 小时前
力扣19删除链表的倒数第N个结点(C++)
c++·算法·leetcode·链表
keep intensify4 小时前
最小路径和
算法·leetcode·职场和发展
多打代码5 小时前
2026.03.23 最长递增子序列 & 最长连续递增序列 & 最长公共子序列
算法·leetcode·职场和发展
Q741_1476 小时前
力扣高频面试题详解 数组 链表 力扣 56.合并区间 力扣 160.相交链表 C++ 每日练习
c++·算法·leetcode·链表·数组·哈希
Tisfy6 小时前
LeetCode 1594.矩阵的最大非负积:动态规划O(mn)
leetcode·矩阵·动态规划·dp
Frostnova丶6 小时前
LeetCode 1594.矩阵中最大的非负乘积
算法·leetcode·矩阵