2304. 网格中的最小路径代价
给你一个下标从 0 开始的整数矩阵 grid ,矩阵大小为 m x n ,由从 0 到 m * n - 1 的不同整数组成。你可以在此矩阵中,从一个单元格移动到 下一行 的任何其他单元格。如果你位于单元格 (x, y) ,且满足 x < m - 1 ,你可以移动到 (x + 1, 0), (x + 1, 1), …, (x + 1, n - 1) 中的任何一个单元格。注意: 在最后一行中的单元格不能触发移动。
每次可能的移动都需要付出对应的代价,代价用一个下标从 0 开始的二维数组 moveCost 表示,该数组大小为 (m * n) x n ,其中 moveCost[i][j] 是从值为 i 的单元格移动到下一行第 j 列单元格的代价。从 grid 最后一行的单元格移动的代价可以忽略。
grid 一条路径的代价是:所有路径经过的单元格的 值之和 加上 所有移动的 代价之和 。从 第一行 任意单元格出发,返回到达 最后一行 任意单元格的最小路径代价。
数据范围
m == grid.length
n == grid[i].length
2 <= m, n <= 50
grid
由从0
到m * n - 1
的不同整数组成moveCost.length == m * n
moveCost[i].length == n
1 <= moveCost[i][j] <= 100
代码
class Solution {
public:
const static int N = 55;
int dp[N][N];
int minPathCost(vector<vector<int>>& grid, vector<vector<int>>& moveCost) {
int n = grid.size(), m = grid[0].size();
memset(dp, 0x3f, sizeof(dp));
for(int i = 1; i <= n; i ++ ) {
for(int j = 1; j <= m; j ++ ) {
if(i == 1) {
dp[i][j] = grid[i - 1][j - 1];
continue;
}
for(int k = 1; k <= m; k ++ ) {
dp[i][j] = min(dp[i][j], dp[i - 1][k] + moveCost[grid[i - 2][k - 1]][j - 1] + grid[i - 1][j - 1]);
}
}
}
int res = 0x3f3f3f3f;
for(int i = 1; i <= m; i ++ ) res = min(res, dp[n][i]);
return res;
}
};
1289. 下降路径最小和 II
给你一个 n x n
整数矩阵 grid
,请你返回 非零偏移下降路径 数字和的最小值。
非零偏移下降路径 定义为:从 grid
数组中的每一行选择一个数字,且按顺序选出来的数字中,相邻数字不在原数组的同一列。
数据范围
n == grid.length == grid[i].length
1 <= n <= 200
-99 <= grid[i][j] <= 99
代码
class Solution {
public:
const static int N = 205;
int dp[N][N];
int minFallingPathSum(vector<vector<int>>& grid) {
int n = grid.size(), m = grid[0].size();
memset(dp, 0x3f, sizeof(dp));
for(int i = 0; i < n; i ++ ) {
for(int j = 0; j < m; j ++ ) {
if(i == 0) {
dp[i + 1][j + 1] = grid[i][j];
continue;
}
for(int k = 0; k < m; k ++ ) {
if(k == j) continue;
dp[i + 1][j + 1] = min(dp[i + 1][j + 1], dp[i][k + 1] + grid[i][j]);
}
}
}
int res = 0x3f3f3f3f;
for(int i = 1; i <= m; i ++ ) res = min(res, dp[n][i]);
return res;
}
};
1594. 矩阵的最大非负积
给你一个大小为 m x n
的矩阵 grid
。最初,你位于左上角 (0, 0)
,每一步,你可以在矩阵中 向右 或 向下 移动。
在从左上角 (0, 0)
开始到右下角 (m - 1, n - 1)
结束的所有路径中,找出具有 最大非负积 的路径。路径的积是沿路径访问的单元格中所有整数的乘积。
返回 最大非负积 对 109 + 7
取余 的结果。如果最大积为 负数 ,则返回-1
。
注意,取余是在得到最大积之后执行的。
数据范围
m == grid.length
n == grid[i].length
1 <= m, n <= 15
-4 <= grid[i][j] <= 4
分析
令dp1[i][j]表示到达(i,j)的最小路径积(负数),dp2[i][j]表示到达(i,1)的最大路径积,则状态转移如下:
-
i
f
g
r
i
d
[
i
]
[
j
]
<
0
if\ grid[i][j]<0
if grid[i][j]<0
- d p 2 [ i + 1 ] [ j + 1 ] = m a x ( d p 1 [ i + 1 ] [ j ] ∗ g r i d [ i ] [ j ] , d p 1 [ i ] [ j + 1 ] ∗ g r i d [ i ] [ j ] ) ; dp2[i + 1][j + 1] = max(dp1[i + 1][j] * grid[i][j], dp1[i][j + 1] * grid[i][j]); dp2[i+1][j+1]=max(dp1[i+1][j]∗grid[i][j],dp1[i][j+1]∗grid[i][j]);
- d p 1 [ i + 1 ] [ j + 1 ] = m i n ( d p 2 [ i + 1 ] [ j ] ∗ g r i d [ i ] [ j ] , d p 2 [ i ] [ j + 1 ] ∗ g r i d [ i ] [ j ] ) ; dp1[i + 1][j + 1] = min(dp2[i + 1][j] * grid[i][j], dp2[i][j + 1] * grid[i][j]); dp1[i+1][j+1]=min(dp2[i+1][j]∗grid[i][j],dp2[i][j+1]∗grid[i][j]);
-
i
f
g
r
i
d
[
i
]
[
j
]
>
=
0
if \ grid[i][j]>=0
if grid[i][j]>=0
- d p 2 [ i + 1 ] [ j + 1 ] = m a x ( d p 2 [ i + 1 ] [ j ] ∗ g r i d [ i ] [ j ] , d p 2 [ i ] [ j + 1 ] ∗ g r i d [ i ] [ j ] ) ; dp2[i + 1][j + 1] = max(dp2[i + 1][j] * grid[i][j], dp2[i][j + 1] * grid[i][j]); dp2[i+1][j+1]=max(dp2[i+1][j]∗grid[i][j],dp2[i][j+1]∗grid[i][j]);
- d p 1 [ i + 1 ] [ j + 1 ] = m i n ( d p 1 [ i + 1 ] [ j ] ∗ g r i d [ i ] [ j ] , d p 1 [ i ] [ j + 1 ] ∗ g r i d [ i ] [ j ] ) ; dp1[i + 1][j + 1] = min(dp1[i + 1][j] * grid[i][j], dp1[i][j + 1] * grid[i][j]); dp1[i+1][j+1]=min(dp1[i+1][j]∗grid[i][j],dp1[i][j+1]∗grid[i][j]);
代码
typedef long long LL;
class Solution {
public:
const static LL N = 20, mod = 1e9 + 7, INF = INT_MAX / 2;
LL dp1[N][N], dp2[N][N];
LL maxProductPath(vector<vector<int>>& grid) {
int n = grid.size(), m = grid[0].size();
LL res = -INF;
bool flag = false;
for(int i = 0; i < n; i ++ ) {
for(int j = 0; j < m; j ++ ) {
if(!grid[i][j]) flag = true;
if(i == 0 && j == 0) {
dp1[i + 1][j + 1] = min(0, grid[i][j]);
dp2[i + 1][j + 1] = max(0, grid[i][j]);
continue;
}
if(grid[i][j] < 0) {
dp2[i + 1][j + 1] = max(dp1[i + 1][j] * grid[i][j], dp1[i][j + 1] * grid[i][j]);
dp1[i + 1][j + 1] = min(dp2[i + 1][j] * grid[i][j], dp2[i][j + 1] * grid[i][j]);
} else {
dp2[i + 1][j + 1] = max(dp2[i + 1][j] * grid[i][j], dp2[i][j + 1] * grid[i][j]);
dp1[i + 1][j + 1] = min(dp1[i + 1][j] * grid[i][j], dp1[i][j + 1] * grid[i][j]);
}
}
}
res = dp2[n][m];
res %= mod;
if(!flag && !res) res = -1;
return res;
}
};