You are given an m x n grid. A robot starts at the top-left corner of the grid (0, 0) and wants to reach the bottom-right corner (m - 1, n - 1). The robot can move either right or down at any point in time.
The grid contains a value coins[i][j] in each cell:
If coins[i][j] >= 0, the robot gains that many coins.
If coins[i][j] < 0, the robot encounters a robber, and the robber steals the absolute value of coins[i][j] coins.
The robot has a special ability to neutralize robbers in at most 2 cells on its path, preventing them from stealing coins in those cells.
Note: The robot’s total coins can be negative.
Return the maximum profit the robot can gain on the route.
This is a grid DP problem with an extra state: the number of robbers neutralized so far (up to 2). At each cell, the robot can move right or down, and if the cell has a robber, it can choose to neutralize (if it has neutralizations left) or not. We use a 3D DP array to track the best profit at each cell and neutralization count.
classSolution {
public:int maximumMoney(vector<vector<int>>& coins) {
int m = coins.size(), n = coins[0].size();
vector<vector<vector<int>>> dp(m, vector<vector<int>>(n, vector<int>(3, INT_MIN)));
dp[0][0][0] = coins[0][0];
if (coins[0][0] <0) dp[0][0][1] =0;
for (int i =0; i < m; ++i) {
for (int j =0; j < n; ++j) {
for (int k =0; k <=2; ++k) {
if (dp[i][j][k] == INT_MIN) continue;
for (int d =0; d <2; ++d) {
int ni = i + (d ==0), nj = j + (d ==1);
if (ni >= m || nj >= n) continue;
int val = coins[ni][nj];
// Not neutralize
int gain = val >=0? val : val;
dp[ni][nj][k] = max(dp[ni][nj][k], dp[i][j][k] + gain);
// Neutralize if robber and k < 2
if (val <0&& k <2)
dp[ni][nj][k+1] = max(dp[ni][nj][k+1], dp[i][j][k]);
}
}
}
}
returnmax({dp[m-1][n-1][0], dp[m-1][n-1][1], dp[m-1][n-1][2]});
}
};
classSolution:
defmaximumMoney(self, coins: list[list[int]]) -> int:
m, n = len(coins), len(coins[0])
dp = [[[-float('inf')]*3for _ in range(n)] for _ in range(m)]
dp[0][0][0] = coins[0][0]
if coins[0][0] <0:
dp[0][0][1] =0for i in range(m):
for j in range(n):
for k in range(3):
if dp[i][j][k] ==-float('inf'):
continuefor di, dj in [(1,0),(0,1)]:
ni, nj = i+di, j+dj
if ni >= m or nj >= n:
continue val = coins[ni][nj]
dp[ni][nj][k] = max(dp[ni][nj][k], dp[i][j][k] + val)
if val <0and k <2:
dp[ni][nj][k+1] = max(dp[ni][nj][k+1], dp[i][j][k])
return max(dp[m-1][n-1])
impl Solution {
pubfnmaximum_money(coins: Vec<Vec<i32>>) -> i32 {
let m = coins.len();
let n = coins[0].len();
letmut dp =vec![vec![vec![i32::MIN; 3]; n]; m];
dp[0][0][0] = coins[0][0];
if coins[0][0] <0 { dp[0][0][1] =0; }
for i in0..m {
for j in0..n {
for k in0..=2 {
if dp[i][j][k] ==i32::MIN { continue; }
for (di, dj) in [(1,0),(0,1)] {
let ni = i+di;
let nj = j+dj;
if ni >= m || nj >= n { continue; }
let val = coins[ni][nj];
dp[ni][nj][k] = dp[ni][nj][k].max(dp[i][j][k] + val);
if val <0&& k <2 {
dp[ni][nj][k+1] = dp[ni][nj][k+1].max(dp[i][j][k]);
}
}
}
}
}
*dp[m-1][n-1].iter().max().unwrap()
}
}