Before attempting this problem, you should be comfortable with:
We want to collect the maximum amount of gold by traversing the grid. Since we can start from any cell containing gold and move in four directions without revisiting cells, this naturally fits a backtracking approach. We try starting from every gold cell and explore all possible paths, keeping track of the maximum gold collected. The key insight is that we need to "undo" our visit after exploring a path so other paths can use that cell.
dfs from that cell.dfs, mark the current cell as visited by adding it to a set.dfs.class Solution:
def getMaximumGold(self, grid: list[list[int]]) -> int:
ROWS, COLS = len(grid), len(grid[0])
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
def dfs(r, c, visit):
if min(r, c) < 0 or r == ROWS or c == COLS or grid[r][c] == 0 or (r, c) in visit:
return 0
visit.add((r, c))
res = grid[r][c]
for dr, dc in directions:
res = max(res, grid[r][c] + dfs(r + dr, c + dc, visit))
visit.remove((r, c))
return res
res = 0
for r in range(ROWS):
for c in range(COLS):
if grid[r][c] != 0:
res = max(res, dfs(r, c, set()))
return resWhere is the number of cells which contain gold.
Instead of using a separate visited set, we can mark cells as visited by temporarily setting them to zero. Since zero represents an empty cell (no gold), the dfs will naturally skip it. After exploring all paths from a cell, we restore its original value. This approach saves space and can be slightly faster since we avoid set operations.
dfs from that cell.dfs, save the current cell's gold value and set the cell to 0 (marking it as visited).dfs and track the maximum gold from neighbors.class Solution:
def getMaximumGold(self, grid: list[list[int]]) -> int:
ROWS, COLS = len(grid), len(grid[0])
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
def dfs(r, c):
if min(r, c) < 0 or r == ROWS or c == COLS or grid[r][c] == 0:
return 0
gold = grid[r][c]
grid[r][c] = 0
res = 0
for dr, dc in directions:
res = max(res, dfs(r + dr, c + dc))
grid[r][c] = gold
return gold + res
res = 0
for r in range(ROWS):
for c in range(COLS):
if grid[r][c] != 0:
res = max(res, dfs(r, c))
return resWhere is the number of cells which contain gold.
We can also solve this problem using BFS with bitmask state tracking. Each cell containing gold is assigned a unique index, and we use a bitmask to track which cells have been visited along the current path. This allows us to explore all possible paths level by level while ensuring we do not revisit any cell within the same path.
bitmask.class Solution:
def getMaximumGold(self, grid: list[list[int]]) -> int:
ROWS, COLS = len(grid), len(grid[0])
directions = [1, 0, -1, 0, 1]
index = [[0] * COLS for _ in range(ROWS)]
idx = 0
for r in range(ROWS):
for c in range(COLS):
if grid[r][c] != 0:
index[r][c] = idx
idx += 1
res = 0
for r in range(ROWS):
for c in range(COLS):
if grid[r][c] > 0:
q = deque([(r, c, grid[r][c], 1 << index[r][c])])
while q:
row, col, gold, mask = q.popleft()
res = max(res, gold)
for i in range(4):
nr, nc = row + directions[i], col + directions[i + 1]
if 0 <= nr < ROWS and 0 <= nc < COLS and grid[nr][nc] > 0:
idx = index[nr][nc]
if not (mask & (1 << idx)):
q.append((nr, nc, gold + grid[nr][nc], mask | (1 << idx)))
return resWhere is the number of cells which contain gold.
The most common mistake is forgetting to restore the cell's state after exploring a path. Whether using a visited set or modifying the grid directly, failing to backtrack means other paths starting from different cells cannot use that position. Always remove the cell from the visited set or restore its original value before returning.
Some solutions incorrectly assume the optimal path must start from a corner or edge. The problem allows starting from any cell containing gold, so you must try all possible starting positions. Missing interior starting cells can lead to suboptimal results.
Cells with value zero cannot be visited, but some solutions forget to check for zeros when determining valid neighbors. Additionally, when using the grid modification approach to mark cells as visited (setting them to zero), ensure you save the original value before modification so it can be properly restored during backtracking.