Problem Statement in English
You’re given a 2D grid of integers grid of size m x n, where grid[i][j] represents the amount of money at cell (i, j).
A robot starts at the top-left corner of the grid and wants to reach the bottom-right corner.
The robot can only move either down or right at any point in time.
However, the robot has a special ability that allows it to shoot up to 2 times. When the robot shoots, it can skip collecting money from a cell with a negative value (i.e., it can treat that cell as if it has a value of 0).
Return the maximum amount of money the robot can earn by the time it reaches the bottom-right corner of the grid.
Approach
To solve this problem, we can use dynamic programming. We will create a 3D DP array dp[i][j][k] where i and j represent the current cell in the grid, and k represents the number of shots used (0, 1, or 2).
The value of dp[i][j][k] will represent the maximum amount of money the robot can earn starting from cell (i, j) with k shots used.
The base case will be the bottom-right corner of the grid, where we can directly take the value of that cell (considering if we need to use a shot or not).
And then we just work our way backwards to the top-left corner, considering the possible moves (right and down) and whether we want to use a shot or not when we encounter a negative value.
Finally, the answer will be in dp[0][0][2], which represents the maximum amount of money the robot can earn starting from the top-left corner with up to 2 shots available.
And we’re done!
Solution in Python
class Solution:
def maximumAmount(self, grid: List[List[int]]) -> int:
M, N = len(grid), len(grid[0])
dp = [[[-inf]*3 for _ in range(N)] for _ in range(M)]
# base case (bottom-right)
for k in range(3):
if grid[M-1][N-1] < 0 and k > 0:
dp[M-1][N-1][k] = 0
else:
dp[M-1][N-1][k] = grid[M-1][N-1]
for i in reversed(range(M)):
for j in reversed(range(N)):
if i == M-1 and j == N-1:
continue
for shots in range(3):
best = -inf
# move right
if j + 1 < N:
best = max(best, grid[i][j] + dp[i][j+1][shots])
if grid[i][j] < 0 and shots > 0:
best = max(best, dp[i][j+1][shots-1])
# move down
if i + 1 < M:
best = max(best, grid[i][j] + dp[i+1][j][shots])
if grid[i][j] < 0 and shots > 0:
best = max(best, dp[i+1][j][shots-1])
dp[i][j][shots] = best
return dp[0][0][2]
Complexity
Time: $O(M \times N \times 3)$
WhereMandNare the dimensions of the grid, and we iterate through each cell and each possible number of shots (0, 1, or 2).Space: $O(M \times N \times 3)$
WhereMandNare the dimensions of the grid, and we store the maximum amount of money for each cell and each possible number of shots.
And we are done.