Problem Statement in English
You’re given a square board of characters. You can move on the board starting at the bottom right square marked with the character ‘S’. You need to move to the top left square marked with the character ‘E’. The rest of the squares are labeled either with a numeric character 1-9 or with an obstacle ‘X’. You cannot move onto obstacles. You can only move up, left, or diagonally up and left.
Return a list of two integers: the first integer is the maximum sum of numeric characters you can collect on your path from ‘S’ to ‘E’, and the second integer is the number of such paths that you can take to get that maximum sum. Since the answer can be large, return it modulo $10^9 + 7$.
Approach
This problem can be solved using dynamic programming. We can define a recursive function that calculates the maximum score and the number of paths to reach each cell in the board. We will use memoization to store the results of previously computed cells to avoid redundant calculations.
At each cell, we will check the three possible directions (up, left, and diagonally up-left) and compute the maximum score and the number of paths from those directions. If a cell is an obstacle or out of bounds, we will skip it.
For each cell we visit, we check if it can actually reach the end ‘E’. If it can, we update the maximum score and the number of paths accordingly. Finally, we return the maximum score and the number of paths from the starting cell ‘S’.
And we’re done!
Solution in Python
class Solution:
def pathsWithMaxScore(self, board: List[str]) -> List[int]:
M, N = len(board), len(board[0])
MOD = 10 ** 9 + 7
directions = [(0, -1), (-1, 0), (-1, -1)]
@cache
def dp(i, j):
# Base Case: Reached the end successfully
if board[i][j] == "E":
return [0, 1] # [score, paths]
best_score = -float('inf')
best_paths = 0
# Check all 3 movements
for dx, dy in directions:
nx, ny = i + dx, j + dy
# Out of bounds or obstacle
if not (0 <= nx < M and 0 <= ny < N) or board[nx][ny] == "X":
continue
next_score, next_paths = dp(nx, ny)
# If the next square can actually reach 'E'
if next_score != -float('inf'):
if next_score > best_score:
best_score = next_score
best_paths = next_paths
elif next_score == best_score:
best_paths = (best_paths + next_paths) % MOD
# If no valid paths could reach 'E' from here
if best_score == -float('inf'):
return [-float('inf'), 0]
# Add current square's value (0 for 'S')
current_val = 0 if board[i][j] == "S" else int(board[i][j])
return [best_score + current_val, best_paths]
ans_score, ans_paths = dp(M - 1, N - 1)
# If 'E' is unreachable from 'S'
if ans_score == -float('inf'):
return [0, 0]
return [ans_score, ans_paths]
Complexity
Time: $O(M \times N)$
Since we iterate over all cells in the board once.Space: $O(M \times N)$
Since we iterate over all cells in the board once.
Mistakes I Made
I overcomplicated the implementation.
And we are done.