Rat in a Maze with multiple steps or jump allowed

Last Updated : 23 Jun, 2026

Given a matrix mat[][] of size n × n, where mat[i][j] represents the maximum number of steps a rat can jump either forward (right) or downward from that cell, find a path for the rat to reach from the top-left cell (0, 0) to the bottom-right cell (n - 1, n - 1).  A cell containing 0 is blocked and cannot be used in the path. It is guaranteed that the cell mat[n-1][n-1] is not 0.

Return an n × n matrix where 1 represents the cells included in the path and 0 represents the remaining cells.

Note: If multiple valid paths exist, choose the path with the shortest possible jumps first. For the same jump length, moving forward (right) should be preferred over moving downward.

Examples:  

Input: mat[][] = [[2, 1, 0, 0], [3, 0, 0, 1], [0, 1, 0, 1], [0, 0, 0, 1]]
Output: [[1, 0, 0, 0], [1, 0, 0, 1], [0, 0, 0, 1], [0, 0, 0, 1]]
Explanation:

2056958389

The rat starts from cell (0, 0) which contains value 2, so it can jump at most 2 steps either right or downward. Steps: -> Moves downward to (1, 0) which contains value 3. -> Jumps 3 steps right to reach (1, 3). -> Moves downward through (2, 3) and reaches the destination cell (3, 3).

Input: mat[][] = [[2, 1, 0, 0], [2, 0, 0, 1], [0, 1, 0, 1], [0, 0, 0, 1]]
Output: [[-1]]
Explanation: The rat starts at (0, 0) with value 2, but every possible path from there eventually reaches a cell containing 0. Since no sequence of jumps can reach the destination cell (3, 3), no valid path exists and the output is [[-1]].

Try It Yourself
redirect icon

Using Recursion + Backtracking - O(2^(n^2)) Time and O(n^2) Space

The idea is to explore all possible paths from (0,0) to (n-1,n-1) using recursive traversal while ensuring each move stays within bounds, avoids blocked cells, and prevents revisiting. At each step, it prioritizes moving right first, then down, attempting all possible jumps allowed by the current cell. If a path reaches the destination, it returns the path matrix; otherwise, it backtracks and explores alternatives. If no valid path exists, it returns -1.

  • Recursively explore paths by making jumps in the right and downward directions.
  • Handle the base case: If the destination (n-1, n-1) is reached, mark the cell and return true.
  • Backtrack if a path fails by resetting the cell and trying the next possibility.
  • Generate the output matrix by storing the path taken in a separate 2D array and returning it if a valid path exists.
  • Handle the no solution case: If no path is found, return a matrix containing -1.
C++
#include <bits/stdc++.h>
using namespace std;

// Function to check if the cell is valid
bool isSafe(int row, int col, int n, 
            vector<vector<int>>& mat) {
    return (row >= 0 && row < n && col >= 0 && 
            col < n && mat[row][col] != 0);
}

// Recursive function to find the path
bool findPath(vector<vector<int>>& mat, 
              vector<vector<int>>& path, 
              int row, int col, int n) {
    
    // Base case: If destination is reached
    if (row == n - 1 && col == n - 1) {
        path[row][col] = 1;
        return true;
    }

    // Check if cell is valid and not visited
    if (isSafe(row, col, n, mat) && 
        !path[row][col]) {
        
        // Mark cell
        path[row][col] = 1; 

        // Try moving right first
        for (int jump = 1; jump <= mat[row][col] 
                           && jump < n; jump++) {
            if (findPath(mat, path, row, col + jump, n)) 
                return true;
            if (findPath(mat, path, row + jump, col, n)) 
                return true;
        }
        
        // Backtrack
        path[row][col] = 0;
        return false;
    }
    return false;
}

// Function to get the shortest path matrix
vector<vector<int>> shortestDist(vector<vector<int>>& mat) {
    int n = mat.size();

    // Initialize path matrix
    vector<vector<int>> path(n, vector<int>(n, 0));

    // If no path exists, return -1
    if (!findPath(mat, path, 0, 0, n)) 
        return {{-1}};

    return path;
}

// Function to print 2D array
void print2dArray(vector<vector<int>>& arr) {
    for (auto& row : arr) {
        for (auto& cell : row) 
            cout << cell << " ";
        cout << endl;
    }
}

int main() {
 
    vector<vector<int>> mat = {
        {2, 1, 0, 0},
        {3, 0, 0, 1},
        {0, 1, 0, 1},
        {0, 0, 0, 1}
    };

    // Get shortest path matrix
    vector<vector<int>> result = 
        shortestDist(mat);

    print2dArray(result);

    return 0;
}
Java
import java.util.*;

class GfG {

    // Function to check if the cell is valid
    static boolean isSafe(int row, int col, int n,
                          int[][] mat)
    {
        return (row >= 0 && row < n && col >= 0 && col < n
                && mat[row][col] != 0);
    }

    static boolean findPath(int[][] mat,
             ArrayList<ArrayList<Integer> > path, int row,
             int col, int n)
    {

        // Base case: If destination is reached
        if (row == n - 1 && col == n - 1) {
            path.get(row).set(col, 1);
            return true;
        }

        // Check if cell is valid and not visited (equals 0)
        if (isSafe(row, col, n, mat)
            && path.get(row).get(col) == 0) {
                
            // Mark cell
            path.get(row).set(col, 1); 

            // Try moving right first
            for (int jump = 1;
                 jump <= mat[row][col] && jump < n;
                 jump++) {
                if (col + jump < n
                    && findPath(mat, path, row, col + jump,
                                n))
                    return true;
                if (row + jump < n
                    && findPath(mat, path, row + jump, col,
                                n))
                    return true;
            }
            
            // Backtrack
            path.get(row).set(col, 0); 
            return false;
        }
        return false;
    }

    // Function to get the shortest path matrix
    static ArrayList<ArrayList<Integer> >
    shortestDist(int[][] mat)
    {
        int n = mat.length;

        ArrayList<ArrayList<Integer> > path
            = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            ArrayList<Integer> row = new ArrayList<>(
                Collections.nCopies(n, 0));
            path.add(row);
        }

        // Call the helper function
        // If no path exists, return [[-1]]
        if (!findPath(mat, path, 0, 0, n)) {
            ArrayList<ArrayList<Integer> > noPath
                = new ArrayList<>();
            ArrayList<Integer> row = new ArrayList<>();
            row.add(-1);
            noPath.add(row);
            return noPath;
        }
 
        return path;
    }

    // Function to print 2D ArrayList
    static void
    print2dArray(ArrayList<ArrayList<Integer> > arr)
    {
        for (int i = 0; i < arr.size(); i++) {
            for (int j = 0; j < arr.get(i).size(); j++) {
                System.out.print(arr.get(i).get(j) + " ");
            }
            System.out.println();
        }
    }

    public static void main(String[] args)
    {
        int[][] mat = { { 2, 1, 0, 0 },
                        { 3, 0, 0, 1 },
                        { 0, 1, 0, 1 },
                        { 0, 0, 0, 1 } };

        // Get shortest path matrix
        ArrayList<ArrayList<Integer> > result
            = shortestDist(mat);

        print2dArray(result);
    }
}
Python
# Function to check if the cell is valid
def isSafe(row, col, n, mat):
    return (row >= 0 and row < n and col >= 0 and
            col < n and mat[row][col] != 0)

# Recursive function to find the path


def findPath(mat, path, row, col, n):

    # Base case: If destination is reached
    if row == n - 1 and col == n - 1:
        path[row][col] = 1
        return True

    # Check if cell is valid and not visited
    if isSafe(row, col, n, mat) and not path[row][col]:

        # Mark cell
        path[row][col] = 1

        # Try moving right first
        for jump in range(1, mat[row][col] + 1):
            if jump < n:
                if col + jump < n and findPath(mat, path, row, col + jump, n):
                    return True
                if row + jump < n and findPath(mat, path, row + jump, col, n):
                    return True

        # Backtrack
        path[row][col] = 0
        return False
    return False

# Function to get the shortest path matrix


def shortestDist(mat):
    n = len(mat)

    # Initialize path matrix
    path = [[0] * n for _ in range(n)]

    # If no path exists, return -1
    if not findPath(mat, path, 0, 0, n):
        return [[-1]]

    return path

# Function to print 2D array


def print2dArray(arr):
    for row in arr:
        for cell in row:
            print(cell, end=" ")
        print()


# Main function
if __name__ == "__main__":
    mat = [
        [2, 1, 0, 0],
        [3, 0, 0, 1],
        [0, 1, 0, 1],
        [0, 0, 0, 1]
    ]

    # Get shortest path matrix
    result = shortestDist(mat)

    print2dArray(result)
C#
using System;
using System.Collections.Generic;

class GfG {

    // Function to check if the cell is valid
    static bool isSafe(int row, int col, int n, int[, ] mat)
    {
        return (row >= 0 && row < n && col >= 0 && col < n
                && mat[row, col] != 0);
    }

    static bool findPath(int[, ] mat, List<List<int> > path,
                         int row, int col, int n)
    {

        // Base case: If destination is reached
        if (row == n - 1 && col == n - 1) {
            path[row][col] = 1;
            return true;
        }

        // Check if cell is valid and not visited
        if (isSafe(row, col, n, mat)
            && path[row][col] == 0) {

            // Mark cell
            path[row][col] = 1;

            // Try moving right first
            for (int jump = 1;
                 jump <= mat[row, col] && jump < n;
                 jump++) {
                if (col + jump < n
                    && findPath(mat, path, row, col + jump,
                                n))
                    return true;
                if (row + jump < n
                    && findPath(mat, path, row + jump, col,
                                n))
                    return true;
            }

            // Backtrack
            path[row][col] = 0;
            return false;
        }
        return false;
    }

    // Function to get the shortest path matrix
    public static List<List<int> > shortestDist(int[, ] mat)
    {
        int n = mat.GetLength(0);

        // Initialize path List of Lists with all 0s
        List<List<int> > path = new List<List<int> >();
        for (int i = 0; i < n; i++) {
            List<int> row = new List<int>();
            for (int j = 0; j < n; j++) {
                row.Add(0);
            }
            path.Add(row);
        }

        // If no path exists, return [[-1]]
        if (!findPath(mat, path, 0, 0, n)) {
            return new List<List<int> >{ new List<int>{
                -1 } };
        }

        return path;
    }

    // Function to print 2D List
    static void print2dList(List<List<int> > arr)
    {
        for (int i = 0; i < arr.Count; i++) {
            for (int j = 0; j < arr[i].Count; j++) {
                Console.Write(arr[i][j] + " ");
            }
            Console.WriteLine();
        }
    }

    static void Main(string[] args)
    {
        int[, ] mat = new int[, ] { { 2, 1, 0, 0 },
                                    { 3, 0, 0, 1 },
                                    { 0, 1, 0, 1 },
                                    { 0, 0, 0, 1 } };
        // Get shortest path matrix
        List<List<int> > result = shortestDist(mat);

        print2dList(result);
    }
}
JavaScript
// Function to check if the cell is valid
function isSafe(row, col, n, mat) {
    return (row >= 0 && row < n && col >= 0 && 
            col < n && mat[row][col] !== 0);
}

// Recursive function to find the path
function findPath(mat, path, row, col, n) {
    
    // Base case: If destination is reached
    if (row === n - 1 && col === n - 1) {
        path[row][col] = 1;
        return true;
    }
    
    // Check if cell is valid and not visited
    if (isSafe(row, col, n, mat) && 
        path[row][col] === 0) {
            
        // Mark cell
        path[row][col] = 1; 
        
        // Try moving right first
        for (let jump = 1; jump <= mat[row][col] && jump < n; jump++) {
            if (col + jump < n && findPath(mat, path, row, col + jump, n)) 
                return true;
            if (row + jump < n && findPath(mat, path, row + jump, col, n)) 
                return true;
        }
        
        // Backtrack
        path[row][col] = 0; 
        return false;
    }
    return false;
}

// Function to get the shortest path matrix
function shortestDist(mat) {
    const n = mat.length;
    
    // Initialize path matrix
    const path = Array(n).fill().map(() => Array(n).fill(0));
    
    // If no path exists, return -1
    if (!findPath(mat, path, 0, 0, n)) 
        return [[-1]];
    
    return path;
}

// Function to print 2D array
function print2dArray(arr) {
    for (let row of arr) {
        console.log(row.join(' '));
    }
}

// Main execution
const mat = [
    [2, 1, 0, 0],
    [3, 0, 0, 1],
    [0, 1, 0, 1],
    [0, 0, 0, 1]
];

// Get shortest path matrix
const result = shortestDist(mat);
print2dArray(result);

Output
1 0 0 0 
1 0 0 1 
0 0 0 1 
0 0 0 1 

[Efficient Approach] Finding Shortest Valid Path – O(n² × maxJump) Time and O(n²) Space

The idea is to use recursion and backtracking to find a valid path from the top-left cell to the bottom-right cell. From each cell, jumps from 1 to the cell value are tried first toward the right and then downward. Memoization is used to avoid recomputing already visited states, while backtracking helps mark and unmark the current path in the answer matrix.

  • Start recursion from cell (0,0)
  • Base cases: Out of bounds -> invalid. Blocked cell -> invalid. Destination reached -> valid path found
  • Mark current cell in answer matrix
  • Try all possible jumps: Move right first, then move downward
  • If no path works, backtrack by removing current cell from path
  • Use DP table to store previously computed results
C++
#include <bits/stdc++.h>
using namespace std;

// Helper function to find path using DFS and Memoization
bool solve(int i, int j, vector<vector<int>> &mat, vector<vector<int>> &ans, vector<vector<int>> &dp)
{

    int n = mat.size();

    // Out of bounds
    if (i >= n || j >= n)
        return false;

    // Destination reached
    if (i == n - 1 && j == n - 1)
    {
        // Mark destination in path
        ans[i][j] = 1; 
        return true;
    }

    // Check if current cell is a blocked cell
    if (mat[i][j] == 0)
        return false;

    // Memoization: if already calculated, return stored result
    if (dp[i][j] != -1)
        return dp[i][j];

    // Mark current cell as part of the answer path
    ans[i][j] = 1;

    int jump = mat[i][j];

    // Shortest jumps first (try 1 step, then 2 steps, etc.)
    for (int step = 1; step <= jump; step++)
    {

        // Try moving right first
        if (solve(i, j + step, mat, ans, dp))
        {
            return dp[i][j] = 1;
        }

        // Try moving down if moving right fails
        if (solve(i + step, j, mat, ans, dp))
        {
            return dp[i][j] = 1;
        }
    }

    // Backtrack: unmark cell if it leads to a dead end
    ans[i][j] = 0;

    return dp[i][j] = 0;  
}

// Function to set up and start finding the shortest distance path
vector<vector<int>> shortestDist(vector<vector<int>> &mat)
{

    int n = mat.size();

    // Special case: 1x1 matrix
    if (n == 1)
        return {{1}};

    // Path matrix initialized to 0
    vector<vector<int>> ans(n, vector<int>(n, 0));

    // Blocked start cell check
    if (mat[0][0] == 0)
        return {{-1}};

    // Memoization table initialized to -1 (unvisited state)
    vector<vector<int>> dp(n, vector<int>(n, -1));

    // Start DFS from (0, 0), return [[-1]] if no path found
    if (!solve(0, 0, mat, ans, dp))
        return {{-1}};

    return ans;
}
 
void print2dArray(vector<vector<int>> &arr)
{
    for (auto &row : arr)
    {
        for (auto &cell : row)
            cout << cell << " ";
        cout << endl;
    }
}

int main()
{

    vector<vector<int>> mat = {{2, 1, 0, 0}, {3, 0, 0, 1}, {0, 1, 0, 1}, {0, 0, 0, 1}};

    // Get shortest path matrix
    vector<vector<int>> result = shortestDist(mat);

    print2dArray(result);

    return 0;
}
Java
import java.util.*;

class Solution {
    
    // Recursive helper function to find the path
    boolean solve(int i, int j, int[][] mat, ArrayList<ArrayList<Integer>> ans, int[][] dp) {
        int n = mat.length;
        
        // Out of bounds
        if (i >= n || j >= n) return false;
        
        // Destination reached
        if (i == n - 1 && j == n - 1) {
            ans.get(i).set(j, 1);  
            return true;
        }
         
        if (mat[i][j] == 0) return false;
        
        // Check memoization table 
        if (dp[i][j] != -1) return dp[i][j] == 1;
        
        // Mark current cell as part of the path
        ans.get(i).set(j, 1);
        int jump = mat[i][j];
        
        // Try all possible jumps 
        for (int step = 1; step <= jump; step++) {
            
            // Try moving right first
            if (j + step < n && solve(i, j + step, mat, ans, dp)) {
                dp[i][j] = 1;  
                return true;
            }
            
            // Try moving down 
            if (i + step < n && solve(i + step, j, mat, ans, dp)) {
                dp[i][j] = 1; 
                return true;
            }
        }
        
        // If no valid path found from this cell, unmark it
        ans.get(i).set(j, 0);
        dp[i][j] = 0;  
        return false;
    }
    
    // Function to get the shortest path matrix
    public ArrayList<ArrayList<Integer>> shortestDist(int[][] mat) {
        int n = mat.length;
        ArrayList<ArrayList<Integer>> ans = new ArrayList<>();
         
        for (int i = 0; i < n; i++) {
            ans.add(new ArrayList<>(Collections.nCopies(n, 0)));
        }
         
        if (n == 1) {
            ans.get(0).set(0, 1);
            return ans;
        } 
        
        if (mat[0][0] == 0) {
            ans.clear();
            ans.add(new ArrayList<>(Arrays.asList(-1)));
            return ans;
        }
        
        // Initialize DP table with -1
        int[][] dp = new int[n][n];
        for (int[] row : dp) {
            Arrays.fill(row, -1);
        }
        
        // Call the helper. If no path is found, return [[-1]]
        if (!solve(0, 0, mat, ans, dp)) {
            ans.clear();
            ans.add(new ArrayList<>(Arrays.asList(-1)));
            return ans;
        }
        
        return ans;
    }
}
Python
class Solution:
    def solve(self, i, j, mat, ans, dp):
        n = len(mat)
        
        # Out of bounds check
        if i >= n or j >= n:
            return False
        
        # Destination reached
        if i == n - 1 and j == n - 1:
            ans[i][j] = 1
            return True
        
        # Blocked cell check
        if mat[i][j] == 0:
            return False
        
        # Return memoized result
        if dp[i][j] != -1:
            return dp[i][j] == 1
        
        ans[i][j] = 1
        jump = mat[i][j]
        
        # Try shorter jumps first
        for step in range(1, jump + 1):
            
            # Jump right
            if j + step < n and self.solve(i, j + step, mat, ans, dp):
                dp[i][j] = 1
                return True
            
            # Jump down
            if i + step < n and self.solve(i + step, j, mat, ans, dp):
                dp[i][j] = 1
                return True
        
        # Backtrack if no path found
        ans[i][j] = 0
        dp[i][j] = 0
        return False

    def shortestDist(self, mat):
        n = len(mat)
        
        # Special case for 1x1 grid
        if n == 1:
            return [[1]]
        
        ans = [[0] * n for _ in range(n)]
        
        # Start cell is blocked
        if mat[0][0] == 0:
            return [[-1]]
        
        dp = [[-1] * n for _ in range(n)]
        
        # Return [[-1]] if no path exists
        if not self.solve(0, 0, mat, ans, dp):
            return [[-1]]
        
        return ans
C#
using System;
using System.Collections.Generic;

class GfG {
    
    static bool solve(int i, int j, int[,] mat, List<List<int>> ans, int[,] dp) {
        int n = mat.GetLength(0);
        
        // Out of bounds
        if (i >= n || j >= n)
            return false;
        
        // Destination
        if (i == n - 1 && j == n - 1) {
            ans[i][j] = 1;
            return true;
        }
        
        // Blocked cell
        if (mat[i, j] == 0)
            return false;
        
        // Memoization
        if (dp[i, j] != -1)
            return dp[i, j] == 1;
        
        ans[i][j] = 1;
        
        int jump = mat[i, j];
        
        // Shortest jumps first
        for (int step = 1; step <= jump; step++) {
            // Right first
            if (j + step < n && solve(i, j + step, mat, ans, dp)) {
                dp[i, j] = 1;
                return true;
            }
            
            // Down
            if (i + step < n && solve(i + step, j, mat, ans, dp)) {
                dp[i, j] = 1;
                return true;
            }
        }
        
        ans[i][j] = 0;
        dp[i, j] = 0;
        return false;
    }
    
    static List<List<int>> shortestDist(int[,] mat) {
        int n = mat.GetLength(0);
        
        List<List<int>> ans = new List<List<int>>();
        for (int i = 0; i < n; i++) {
            List<int> row = new List<int>();
            for (int j = 0; j < n; j++) {
                row.Add(0);
            }
            ans.Add(row);
        }
        
        // Special case matrix size 1
        if (n == 1) {
            ans[0][0] = 1;
            return ans;
        }
        
        // Blocked start
        if (mat[0, 0] == 0)
            return new List<List<int>> { new List<int> { -1 } };
        
        int[,] dp = new int[n, n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                dp[i, j] = -1;
            }
        }
        
        // Call the helper. If no path is found, return [[-1]]
        if (!solve(0, 0, mat, ans, dp))
            return new List<List<int>> { new List<int> { -1 } };
        
        return ans;
    }
    
    static void print2dArray(List<List<int>> arr) {
        foreach (var row in arr) {
            foreach (var cell in row) {
                Console.Write(cell + " ");
            }
            Console.WriteLine();
        }
    }
    
    static void Main(string[] args) {
        int[,] mat = new int[,] {
            { 2, 1, 0, 0 },
            { 3, 0, 0, 1 },
            { 0, 1, 0, 1 },
            { 0, 0, 0, 1 }
        };
        
        // Get shortest path matrix
        List<List<int>> result = shortestDist(mat);
        
        print2dArray(result);
    }
}
JavaScript
function solve(i, j, mat, ans, dp) {
    const n = mat.length;
    
    // out of bounds
    if (i >= n || j >= n)
        return false;
    
    // destination
    if (i === n - 1 && j === n - 1) {
        ans[i][j] = 1;
        return true;
    }
    
    // blocked cell
    if (mat[i][j] === 0)
        return false;
    
    // memoization
    if (dp[i][j] !== -1)
        return dp[i][j] === 1;
    
    ans[i][j] = 1;
    
    const jump = mat[i][j];
    
    // shortest jumps first
    for (let step = 1; step <= jump; step++) {
        // right first
        if (j + step < n && solve(i, j + step, mat, ans, dp)) {
            dp[i][j] = 1;
            return true;
        }
        
        // down
        if (i + step < n && solve(i + step, j, mat, ans, dp)) {
            dp[i][j] = 1;
            return true;
        }
    }
    
    ans[i][j] = 0;
    dp[i][j] = 0;
    return false;
}

function shortestDist(mat) {
    const n = mat.length;
    
    // special case
    if (n === 1)
        return [[1]];
    
    const ans = Array(n).fill().map(() => Array(n).fill(0));
    
    // blocked start
    if (mat[0][0] === 0)
        return [[-1]];
    
    const dp = Array(n).fill().map(() => Array(n).fill(-1));
    
    if (!solve(0, 0, mat, ans, dp))
        return [[-1]];
    
    return ans;
}

function print2dArray(arr) {
    for (const row of arr) {
        console.log(row.join(' '));
    }
}

// Driver code
const mat = [
    [2, 1, 0, 0],
    [3, 0, 0, 1],
    [0, 1, 0, 1],
    [0, 0, 0, 1]
];

// Get shortest path matrix
const result = shortestDist(mat);

print2dArray(result);

Output
1 0 0 0 
1 0 0 1 
0 0 0 1 
0 0 0 1 
Comment