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.
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:
The rat starts from cell (0, 0) which contains value 2, so it can jump at most 2 steps either right or downward.
It first tries moving right to (0, 1), but this path does not lead to the destination.
The rat then moves downward to (1, 0) which contains value 3.
From this cell, it jumps 3 steps to the right and reaches (1, 3).
Since (1, 3) contains value 1, the rat can move downward one step at a time to (2, 3) and finally to (3, 3), which is the destination cell.Input: mat[][] = [[2, 1, 0, 0],
[2, 0, 0, 1],
[0, 1, 0, 1],
[0, 0, 0, 1]]
Output: [[-1]]
Explanation:
The rat starts from cell (0, 0) which contains value 2, so it can jump at most 2 steps either right or downward.
However, every possible path eventually gets blocked by cells containing 0, making it impossible to reach the destination cell (3, 3).
Therefore, no valid path exists and the output is [[-1]].
Table of Content
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++ program for Rat Maze With Multiple
// Jumps using Recursion + Backtracking
#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]) {
path[row][col] = 1; // Mark cell
// 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;
}
path[row][col] = 0; // Backtrack
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 program for Rat Maze With Multiple Jumps
// using Recursion + Backtracking
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);
}
// Recursive function to find the path
static boolean findPath(int[][] mat, 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) {
path[row][col] = 1; // Mark cell
// 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;
}
path[row][col] = 0; // Backtrack
return false;
}
return false;
}
// Function to get the shortest path matrix
static int[][] shortestDist(int[][] mat) {
int n = mat.length;
// Initialize path matrix
int[][] path = new int[n][n];
// If no path exists, return -1
if (!findPath(mat, path, 0, 0, n))
return new int[][]{{-1}};
return path;
}
// Function to print 2D array
static void print2dArray(int[][] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][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
int[][] result = shortestDist(mat);
print2dArray(result);
}
}
# Python program for Rat Maze With Multiple Jumps
# using Recursion + Backtracking
# 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]:
path[row][col] = 1 # Mark cell
# 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
path[row][col] = 0 # Backtrack
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# program for Rat Maze With Multiple Jumps
// using Recursion + Backtracking
using System;
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);
}
// Recursive function to find the path
static bool findPath(int[,] mat, 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) {
path[row, col] = 1; // Mark cell
// 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;
}
path[row, col] = 0; // Backtrack
return false;
}
return false;
}
// Function to get the shortest path matrix
static int[,] shortestDist(int[,] mat) {
int n = mat.GetLength(0);
// Initialize path matrix
int[,] path = new int[n, n];
// If no path exists, return -1
if (!findPath(mat, path, 0, 0, n))
return new int[,] { { -1 } };
return path;
}
// Function to print 2D array
static void print2dArray(int[,] arr) {
int rows = arr.GetLength(0);
int cols = arr.GetLength(1);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
Console.Write(arr[i, j] + " ");
}
Console.WriteLine();
}
}
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
int[,] result = shortestDist(mat);
print2dArray(result);
}
}
// JavaScript program for Rat Maze With Multiple Jumps
// using Recursion + Backtracking
// 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) {
path[row][col] = 1; // Mark cell
// 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;
}
path[row][col] = 0; // Backtrack
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
1to 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
#include <bits/stdc++.h>
using namespace std;
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
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];
ans[i][j] = 1;
int jump = mat[i][j];
// shortest jumps first
for (int step = 1; step <= jump; step++)
{
// right first
if (solve(i, j + step, mat, ans, dp))
{
return dp[i][j] = 1;
}
// down
if (solve(i + step, j, mat, ans, dp))
{
return dp[i][j] = 1;
}
}
ans[i][j] = 0;
return dp[i][j] = 0;
}
vector<vector<int>> shortestDist(vector<vector<int>> &mat)
{
int n = mat.size();
// special case
if (n == 1)
return {{1}};
vector<vector<int>> ans(n, vector<int>(n, 0));
// blocked start
if (mat[0][0] == 0)
return {{-1}};
vector<vector<int>> dp(n, vector<int>(n, -1));
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 program for Rat Maze With Multiple Jumps using Memoization
import java.util.*;
class GfG {
static boolean solve(int i, int j, int[][] mat, int[][] ans, int[][] dp) {
int 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;
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 int[][] shortestDist(int[][] mat) {
int n = mat.length;
// special case
if (n == 1)
return new int[][]{{1}};
int[][] ans = new int[n][n];
// blocked start
if (mat[0][0] == 0)
return new int[][]{{-1}};
int[][] dp = new int[n][n];
for (int i = 0; i < n; i++) {
Arrays.fill(dp[i], -1);
}
if (!solve(0, 0, mat, ans, dp))
return new int[][]{{-1}};
return ans;
}
static void print2dArray(int[][] arr) {
for (int[] row : arr) {
for (int cell : row) {
System.out.print(cell + " ");
}
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
int[][] result = shortestDist(mat);
print2dArray(result);
}
}
# Python program for Rat Maze With Multiple Jumps using Memoization
def solve(i, j, mat, ans, dp):
n = len(mat)
# out of bounds
if i >= n or j >= n:
return False
# destination
if i == n - 1 and 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
jump = mat[i][j]
# shortest jumps first
for step in range(1, jump + 1):
# right first
if j + step < n and solve(i, j + step, mat, ans, dp):
dp[i][j] = 1
return True
# down
if i + step < n and solve(i + step, j, mat, ans, dp):
dp[i][j] = 1
return True
ans[i][j] = 0
dp[i][j] = 0
return False
def shortestDist(mat):
n = len(mat)
# special case
if n == 1:
return [[1]]
ans = [[0] * n for _ in range(n)]
# blocked start
if mat[0][0] == 0:
return [[-1]]
dp = [[-1] * n for _ in range(n)]
if not solve(0, 0, mat, ans, dp):
return [[-1]]
return ans
def print2dArray(arr):
for row in arr:
print(' '.join(map(str, row)))
# Driver code
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# program for Rat Maze With Multiple Jumps using Memoization
using System;
class GfG {
static bool solve(int i, int j, int[][] mat, int[][] ans, int[][] dp) {
int 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;
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 int[][] shortestDist(int[][] mat) {
int n = mat.Length;
// special case
if (n == 1)
return new int[][] { new int[] { 1 } };
int[][] ans = new int[n][];
for (int i = 0; i < n; i++) {
ans[i] = new int[n];
}
// blocked start
if (mat[0][0] == 0)
return new int[][] { new int[] { -1 } };
int[][] dp = new int[n][];
for (int i = 0; i < n; i++) {
dp[i] = new int[n];
for (int j = 0; j < n; j++) {
dp[i][j] = -1;
}
}
if (!solve(0, 0, mat, ans, dp))
return new int[][] { new int[] { -1 } };
return ans;
}
static void print2dArray(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[][] {
new int[] { 2, 1, 0, 0 },
new int[] { 3, 0, 0, 1 },
new int[] { 0, 1, 0, 1 },
new int[] { 0, 0, 0, 1 }
};
// Get shortest path matrix
int[][] result = shortestDist(mat);
print2dArray(result);
}
}
// JavaScript program for Rat Maze With Multiple Jumps using Memoization
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