Maximum Number of Moves in a Grid

Updated on 17 June, 2025
Maximum Number of Moves in a Grid header image

Problem Statement

In the given task, you are presented with a 0-indexed m x n matrix filled with positive integers. The problem requires you to determine the longest sequence of movement from the first column to the rightmost column of the matrix, under specific movement constraints. From any selected cell (row, col), you may move to:

  • (row - 1, col + 1) — moving up diagonally to the right.
  • (row, col + 1) — moving directly to the right.
  • (row + 1, col + 1) — moving down diagonally to the right.

But there's a catch—each move destination must contain a number strictly greater than the current cell's value. The challenge is to start from any cell in the first column and identify the maximum number of valid moves you can execute following these rules.

Examples

Example 1

Input:

grid = [[2,4,3,5],[5,4,9,3],[3,4,2,11],[10,9,13,15]]

Output:

3

Explanation:

We can start at the cell (0, 0) and make the following moves:
- (0, 0) -> (0, 1).
- (0, 1) -> (1, 2).
- (1, 2) -> (2, 3).
It can be shown that it is the maximum number of moves that can be made.

Example 2

Input:

grid = [[3,2,4],[2,1,9],[1,1,7]]

Output:

0

Explanation:

Starting from any cell in the first column we cannot perform any moves.

Constraints

  • m == grid.length
  • n == grid[i].length
  • 2 <= m, n <= 1000
  • 4 <= m * n <= 105
  • 1 <= grid[i][j] <= 106

Approach and Intuition

Given the dynamic nature of the matrix traversal, the problem can be efficiently addressed using dynamic programming:

  1. Initialization:

    • Create a dp grid where dp[i][j] represents the maximum number of moves that can be made starting from cell (i, j).
    • Each cell on the last column (n-1) is initialized to 0 as no moves can initiate from these cells.
  2. Propagation:

    • For every other cell, compute the maximum moves by considering potential cells it can transition into (using the allowed movements):
      • For dp[row][col], look at cells (row-1, col+1), (row, col+1), and (row+1, col+1), ensuring they are within grid bounds and their values are greater than grid[row][col].
    • Calculate dp[row][col] as 1 + max(valid transitions). The '+1' accounts for the move made to the maximum transition cell.
  3. Result Extraction:

    • Since you can start from any cell in the first column, the answer will be max(dp[i][0]) for i ranging from 0 to m-1.

This approach ensures that all potential move sequences are considered, and by using dynamic programming, redundant calculations are minimized, adhering to the constraints provided.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    int optimalMoves(vector<vector<int>>& matrix) {
        int rows = matrix.size(), cols = matrix[0].size();
    
        vector<vector<int>> table(rows, vector<int>(2, 0));
    
        for (int r = 0; r < rows; r++) {
            table[r][0] = 1;
        }
    
        int maxResult = 0;
        for (int col = 1; col < cols; col++) {
            for (int row = 0; row < rows; row++) {
                if (matrix[row][col] > matrix[row][col - 1] && table[row][0] > 0) {
                    table[row][1] = max(table[row][1], table[row][0] + 1);
                }
                if (row - 1 >= 0 && matrix[row][col] > matrix[row - 1][col - 1] &&
                    table[row - 1][0] > 0) {
                    table[row][1] = max(table[row][1], table[row - 1][0] + 1);
                }
                if (row + 1 < rows && matrix[row][col] > matrix[row + 1][col - 1] &&
                    table[row + 1][0] > 0) {
                    table[row][1] = max(table[row][1], table[row + 1][0] + 1);
                }
    
                maxResult = max(maxResult, table[row][1] - 1);
            }
    
            for (int k = 0; k < rows; k++) {
                table[k][0] = table[k][1];
                table[k][1] = 0;
            }
        }
    
        return maxResult;
    }
};

In this CPP (C++) solution, the objective is to determine the maximum number of valid moves in a grid, represented as a matrix where each cell can have varying movement rules. The solution involves populating and analyzing a dynamic programming table for optimal paths.

The optimalMoves function processes the matrix to ascertain the peak sequential move count across a grid. This method employs a memoization table, table, initialized based on the matrix dimensions and used to record possible moves per cell.

The approach uses the following techniques:

  • Initializes the first column of the memoization table to signify you can always start moving from any row in the first column.
  • Iterates through the matrix using nested loops:
    1. The outer loop iterates through columns.
    2. The inner loop iterates through rows.
  • Within the inner loop, evaluates potential moves based on cell comparisons between the current cell and its left, upper-left, and lower-left neighbors, updating the current position's maximum possible count for the sequential moves.
  • Updates an accumulator maxResult with the highest value calculated for advance moves throughout the grid configuration.
  • At the end of each column processing, transitions the state of the memoization table for the next column's calculations.

Upon completion of the matrix traversal, the function returns maxResult, representing the maximum number of valid consecutive moves attainable within the grid, following the defined movement criteria. This implementation effectively tracks and updates potential moves through dynamic programming, optimizing the calculations for large matrices.

java
class Solution {
    
    public int calculateMax(int[][] matrix) {
        int rows = matrix.length, cols = matrix[0].length;
    
        int[][] dp = new int[rows][2];
    
        for (int r = 0; r < rows; r++) {
            dp[r][0] = 1;
        }
    
        int maximumMoves = 0;
    
        for (int col = 1; col < cols; col++) {
            for (int row = 0; row < rows; row++) {
                if (matrix[row][col] > matrix[row][col - 1] && dp[row][0] > 0) {
                    dp[row][1] = Math.max(dp[row][1], dp[row][0] + 1);
                }
                if (row - 1 >= 0 && matrix[row][col] > matrix[row - 1][col - 1] && dp[row - 1][0] > 0) {
                    dp[row][1] = Math.max(dp[row][1], dp[row - 1][0] + 1);
                }
                if (row + 1 < rows && matrix[row][col] > matrix[row + 1][col - 1] && dp[row + 1][0] > 0) {
                    dp[row][1] = Math.max(dp[row][1], dp[row + 1][0] + 1);
                }
    
                maximumMoves = Math.max(maximumMoves, dp[row][1] - 1);
            }
    
            for (int r = 0; r < rows; r++) {
                dp[r][0] = dp[r][1];
                dp[r][1] = 0;
            }
        }
    
        return maximumMoves;
    }
}

In the "Maximum Number of Moves in a Grid" problem, the implementation involves calculating the path in a matrix that allows the maximum number of increasing moves in any direction (right or diagonally) from a starting point. This task is managed by employing a dynamic programming approach with Java.

  • Define a method calculateMax that computes the maximum number of allowable sequential moves in an integer matrix.
  • Utilize a 2D integer array (dp) with the same number of rows as the matrix and two columns to track the interim and final results for the maximum number of moves from each cell.
  • Initialize the first column of this dp array to 1 for all rows, reflecting the minimum possible moves from such a position.
  • Iterate through each column (starting from the second column) and explore three potential moves for each cell: directly to the right, diagonally right-up, and diagonally right-down. Use conditions to ensure these moves follow an increasing order and are within the matrix boundaries.
  • Update the dp array's current values based on the maximum moves calculated from the above conditions.
  • After processing each column, transfer the computed possible moves to be the previous column values for the next iteration, and reset the current values.
  • Finally, track and update a variable maximumMoves through each iteration, which holds the global maximum of moves encountered.

The method correctly concludes by returning the calculated maximum moves, which takes into account the nature of transitions between cells and correctly manages boundaries and maximum calculations. The solution leverages dynamic programming effectively to optimize the retrieval of results, making the process efficient and the implementation compact.

python
class GameSolver:
    def bestPath(self, maze: List[List[int]]) -> int:
        rows, cols = len(maze), len(maze[0])
    
        # Initialize DP table for storing intermediate results
        dp_table = [[0] * 2 for _ in range(rows)]
    
        # Mark first column as accessible
        for row in range(rows):
            dp_table[row][0] = 1
    
        max_paths = 0
    
        # Processing all columns except the first
        for col in range(1, cols):
            for row in range(rows):
                # Continue path from left in the same row
                if maze[row][col] > maze[row][col - 1] and dp_table[row][0] > 0:
                    dp_table[row][1] = max(dp_table[row][1], dp_table[row][0] + 1)
    
                # Continue path from upper left diagonal cell
                if (
                    row - 1 >= 0
                    and maze[row][col] > maze[row - 1][col - 1]
                    and dp_table[row - 1][0] > 0
                ):
                    dp_table[row][1] = max(dp_table[row][1], dp_table[row - 1][0] + 1)
    
                # Continue path from lower left diagonal cell
                if (
                    row + 1 < rows
                    and maze[row][col] > maze[row + 1][col - 1]
                    and dp_table[row + 1][0] > 0
                ):
                    dp_table[row][1] = max(dp_table[row][1], dp_table[row + 1][0] + 1)
    
                # Record the highest number of paths from all possibilities
                max_paths = max(max_paths, dp_table[row][1] - 1)
    
            # Update for the next column
            for r in range(rows):
                dp_table[r][0] = dp_table[r][1]
                dp_table[r][1] = 0
    
        return max_paths

The Python code defines a class GameSolver which contains a method bestPath to find the maximum number of moves possible through a grid (or maze), based on strictly increasing values from one cell to an adjacent cell (right, upper right diagonal, lower right diagonal). Here's a brief overview of the solution approach implemented in this code:

  • Initialize a 2D list dp_table to store the intermediate results of the possible paths up to each cell. This table leverages dynamic programming by using two columns to represent the current and previous results, thereby minimizing space usage.

  • The first column of the grid is set as accessible, implying that at least one move is possible starting from any cell in the first column.

  • Iterate over all columns of the grid except the first one, and for each cell:

    • Consider continuation from the left cell if it's a valid increment.
    • Consider diagonally from the upper left cell if it's a valid increment.
    • Consider diagonally from the lower left cell if it's a valid increment.
    • Keep track of the maximum paths possible by comparing and storing the highest values.
  • After processing a column, transfer the newly computed values in the second column of dp_table back to the first for use in the next iteration, resetting the second column afterwards.

  • The function returns max_paths, reflecting the maximum number of moves from the starting column to the last, following the rules of movement defined.

This code effectively finds the path with the highest number of moves satisfying the conditions given by the maze matrix, ensuring an optimal solution through dynamic programming techniques and careful updating of state between iterations.

Comments

No comments yet.