Shortest Path in a Binary Maze (original) (raw)

Given a binary matrix **mat[][] of size **n × m containing values 0 and 1, and a source cell **src[] and destination cell **dest[], find the minimum number of steps required to reach the destination cell from the source cell. From any cell, you can move to its adjacent cells in the up, down, left, and right directions.

If the destination cannot be reached from the source, return -1.

**Example:

**Input: mat[][] = {{1, 1, 1, 1},{1, 1, 0, 1},{1, 1, 1, 1},{1, 1, 0, 0},{1, 0, 0, 1}}, src[] = {0, 1}, dest[] = {2, 2}
**Output: 3
**Explanation: From (0,1), the minimum number of steps to reach (2,2) is 3,

qq

**Input: mat[][] = {{1, 1, 1, 1, 1},{1, 1, 1, 1, 1},{1, 1, 1, 1, 0},{1, 0, 1, 0, 1}}, src[] = {0, 0}, dest[] = {3, 4}
****Output:**-1
**Explanation: From (0,0), the destination (3,4) cannot be reached because all possible paths are blocked by 0 cells, so no valid route exists.

ww

Table of Content

[Naive Approach] Using DFS - O(4^n*m) Time and O(m × n) Space

The idea is to start from the source cell and recursively explore all possible paths to reach the destination cell in the binary matrix. From any cell, we can move in four possible directions: up, down, left, and right, as long as the next cell is valid (inside the grid, not blocked, and not already visited in the current path).

We maintain a visited matrix to avoid cycles and ensure we do not revisit the same cell in a single path. A global variable minDist is used to store the minimum distance found across all possible paths.

Base Cases:

The recurrence relation will be: **dfs(x, y) = **dfs(x+1, y) + dfs(x-1, y) + dfs(x, y+1) + dfs(x, y-1)

C++ `

#include #include #include using namespace std;

// Stores the minimum distance found from source to destination int minDist = INT_MAX;

// Function to check if a cell is safe to visit bool isSafe(vector<vector> &mat, vector<vector> &vis, int x, int y) {

int n = mat.size();
int m = mat[0].size();

// Check boundary conditions, cell value, and whether already visited
return (x >= 0 && x < n &&
        y >= 0 && y < m &&
        mat[x][y] == 1 &&
        !vis[x][y]);

}

// DFS function to explore all possible paths void dfs(vector<vector> &mat, vector<vector> &vis, int x, int y, int dx, int dy, int dist) {

// If destination is reached, update minimum distance
if (x == dx && y == dy) {
    minDist = min(minDist, dist);
    return;
}

// Mark current cell as visited
vis[x][y] = true;

// Possible movements: Up, Down, Left, Right
int dirX[] = {-1, 1, 0, 0};
int dirY[] = {0, 0, -1, 1};

// Try all 4 directions
for (int i = 0; i < 4; i++) {

    int nx = x + dirX[i];
    int ny = y + dirY[i];

    // If next move is valid, continue DFS
    if (isSafe(mat, vis, nx, ny)) {
        dfs(mat, vis, nx, ny, dx, dy, dist + 1);
    }
}

// Backtrack: unmark the cell so other paths can use it
vis[x][y] = false;

}

// Wrapper function to calculate shortest path int shortestPath(vector<vector> &mat, vector &src, vector &dest) {

int n = mat.size();
int m = mat[0].size();

// If source or destination is blocked, return -1
if (mat[src[0]][src[1]] == 0 ||
    mat[dest[0]][dest[1]] == 0)
    return -1;

// Visited matrix to avoid cycles
vector<vector<bool>> vis(n, vector<bool>(m, false));

// Initialize minimum distance
minDist = INT_MAX;

// Start DFS from source cell
dfs(mat, vis,
    src[0], src[1],
    dest[0], dest[1],
    0);

// If no path found, return -1
return (minDist == INT_MAX) ? -1 : minDist;

}

int main() {

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

vector<int> src = {0, 1};
vector<int> dest = {2, 2};
cout << shortestPath(mat, src, dest);

return 0;

}

Java

import java.util.*;

class Solution {

// Stores the minimum distance found from source to destination
static int minDist = Integer.MAX_VALUE;

// Function to check if a cell is safe to visit
static boolean isSafe(int[][] mat,
                      boolean[][] vis,
                      int x, int y) {

    int n = mat.length;
    int m = mat[0].length;

    // Check boundary conditions, cell value, and whether already visited
    return (x >= 0 && x < n &&
            y >= 0 && y < m &&
            mat[x][y] == 1 &&
            !vis[x][y]);
}

// DFS function to explore all possible paths
static void dfs(int[][] mat,
                boolean[][] vis,
                int x, int y,
                int dx, int dy,
                int dist) {

    // If destination is reached, update minimum distance
    if (x == dx && y == dy) {
        minDist = Math.min(minDist, dist);
        return;
    }

    // Mark current cell as visited
    vis[x][y] = true;

    // Possible movements: Up, Down, Left, Right
    int[] dirX = {-1, 1, 0, 0};
    int[] dirY = {0, 0, -1, 1};

    // Try all 4 directions
    for (int i = 0; i < 4; i++) {

        int nx = x + dirX[i];
        int ny = y + dirY[i];

        // If next move is valid, continue DFS
        if (isSafe(mat, vis, nx, ny)) {
            dfs(mat, vis, nx, ny, dx, dy, dist + 1);
        }
    }

    // Backtrack: unmark the cell so other paths can use it
    vis[x][y] = false;
}

static int shortestPath(int[][] mat,
                        int[] src,
                        int[] dest) {

    int n = mat.length;
    int m = mat[0].length;

    // If source or destination is blocked, return -1
    if (mat[src[0]][src[1]] == 0 ||
        mat[dest[0]][dest[1]] == 0)
        return -1;

    boolean[][] vis = new boolean[n][m];

    // Initialize minimum distance
    minDist = Integer.MAX_VALUE;

    // Start DFS from source cell
    dfs(mat, vis,
        src[0], src[1],
        dest[0], dest[1],
        0);

    // If no path found, return -1
    return (minDist == Integer.MAX_VALUE) ? -1 : minDist;
}

}

Python

Stores the minimum distance found from source to destination

minDist = float('inf')

Function to check if a cell is safe to visit

def isSafe(mat, vis, x, y):

n = len(mat)
m = len(mat[0])

# Check boundary conditions, cell value, and whether already visited
return (0 <= x < n and
        0 <= y < m and
        mat[x][y] == 1 and
        not vis[x][y])

DFS function to explore all possible paths

def dfs(mat, vis, x, y, dx, dy, dist):

global minDist

# If destination is reached, update minimum distance
if x == dx and y == dy:
    minDist = min(minDist, dist)
    return

# Mark current cell as visited
vis[x][y] = True

# Possible movements: Up, Down, Left, Right
dirX = [-1, 1, 0, 0]
dirY = [0, 0, -1, 1]

# Try all 4 directions
for i in range(4):

    nx = x + dirX[i]
    ny = y + dirY[i]

    # If next move is valid, continue DFS
    if isSafe(mat, vis, nx, ny):
        dfs(mat, vis, nx, ny, dx, dy, dist + 1)

# Backtrack: unmark the cell so other paths can use it
vis[x][y] = False

Wrapper function to calculate shortest path

def shortestPath(mat, src, dest):

global minDist

n = len(mat)
m = len(mat[0])

# If source or destination is blocked
if mat[src[0]][src[1]] == 0 or mat[dest[0]][dest[1]] == 0:
    return -1

# Visited matrix
vis = [[False for _ in range(m)] for _ in range(n)]

# Initialize minimum distance
minDist = float('inf')

# Start DFS from source cell
dfs(mat, vis,
    src[0], src[1],
    dest[0], dest[1],
    0)

# If no path found
return -1 if minDist == float('inf') else minDist

if name == "main":

mat = [
    [1, 1, 1, 1],
    [1, 1, 0, 1],
    [1, 1, 1, 1],
    [1, 1, 0, 0],
    [1, 0, 0, 1]
]

src = [0, 1]
dest = [2, 2]

print(shortestPath(mat, src, dest))

C#

using System; using System.Collections.Generic;

class GFG {

// Stores the minimum distance found from source to destination
static int minDist = Int32.MaxValue;

// Function to check if a cell is safe to visit
static bool isSafe(int[][] mat, bool[][] vis, int x, int y) {

    int n = mat.Length;
    int m = mat[0].Length;

    // Check boundary conditions, cell value, and whether already visited
    return (x >= 0 && x < n &&
            y >= 0 && y < m &&
            mat[x][y] == 1 &&
            !vis[x][y]);
}

// DFS function to explore all possible paths
static void dfs(int[][] mat, bool[][] vis,
                int x, int y,
                int dx, int dy,
                int dist) {

    // If destination is reached, update minimum distance
    if (x == dx && y == dy) {
        minDist = Math.Min(minDist, dist);
        return;
    }

    // Mark current cell as visited
    vis[x][y] = true;

    // Possible movements: Up, Down, Left, Right
    int[] dirX = { -1, 1, 0, 0 };
    int[] dirY = { 0, 0, -1, 1 };

    // Try all 4 directions
    for (int i = 0; i < 4; i++) {

        int nx = x + dirX[i];
        int ny = y + dirY[i];

        // If next move is valid, continue DFS
        if (isSafe(mat, vis, nx, ny)) {
            dfs(mat, vis, nx, ny, dx, dy, dist + 1);
        }
    }

    // Backtrack: unmark the cell so other paths can use it
    vis[x][y] = false;
}

static int shortestPath(int[][] mat, int[] src, int[] dest) {

    int n = mat.Length;
    int m = mat[0].Length;

    // If source or destination is blocked
    if (mat[src[0]][src[1]] == 0 ||
        mat[dest[0]][dest[1]] == 0)
        return -1;

    bool[][] vis = new bool[n][];
    for (int i = 0; i < n; i++)
        vis[i] = new bool[m];

    minDist = Int32.MaxValue;

    dfs(mat, vis,
        src[0], src[1],
        dest[0], dest[1],
        0);

    return (minDist == Int32.MaxValue) ? -1 : minDist;
}

// Main
static void Main() {

    int[][] mat = new int[][] {
        new int[] {1,1,1,1},
        new int[] {1,1,0,1},
        new int[] {1,1,1,1},
        new int[] {1,1,0,0},
        new int[] {1,0,0,1}
    };

    int[] src = {0, 1};
    int[] dest = {2, 2};

    Console.WriteLine(shortestPath(mat, src, dest));
}

}

JavaScript

"use strict";

// Stores the minimum distance found from source to destination let minDist = Infinity;

// Function to check if a cell is safe to visit function isSafe(mat, vis, x, y) {

let n = mat.length;
let m = mat[0].length;

// Check boundary conditions, cell value, and whether already visited
return (x >= 0 && x < n &&
        y >= 0 && y < m &&
        mat[x][y] === 1 &&
        !vis[x][y]);

}

// DFS function to explore all possible paths function dfs(mat, vis, x, y, dx, dy, dist) {

// If destination is reached, update minimum distance
if (x === dx && y === dy) {
    minDist = Math.min(minDist, dist);
    return;
}

// Mark current cell as visited
vis[x][y] = true;

// Possible movements: Up, Down, Left, Right
let dirX = [-1, 1, 0, 0];
let dirY = [0, 0, -1, 1];

// Try all 4 directions
for (let i = 0; i < 4; i++) {

    let nx = x + dirX[i];
    let ny = y + dirY[i];

    // If next move is valid, continue DFS
    if (isSafe(mat, vis, nx, ny)) {
        dfs(mat, vis, nx, ny, dx, dy, dist + 1);
    }
}

// Backtrack
vis[x][y] = false;

}

// Wrapper function function shortestPath(mat, src, dest) {

let n = mat.length;
let m = mat[0].length;

// If source or destination is blocked
if (mat[src[0]][src[1]] === 0 ||
    mat[dest[0]][dest[1]] === 0)
    return -1;

let vis = Array.from({ length: n }, () => Array(m).fill(false));

minDist = Infinity;

dfs(mat, vis,
    src[0], src[1],
    dest[0], dest[1],
    0);

return (minDist === Infinity) ? -1 : minDist;

}

// Driver code

let mat = [
    [1, 1, 1, 1],
    [1, 1, 0, 1],
    [1, 1, 1, 1],
    [1, 1, 0, 0],
    [1, 0, 0, 1]
];

let src = [0, 1];
let dest = [2, 2];

console.log(shortestPath(mat, src, dest));

`

[Expected Approach] Using BFS - O(n × m) Time and O(n× m) Space

The idea is to use Breadth First Search (BFS) to find the shortest path in the binary matrix. We start from the source cell and explore all reachable cells level by level using a queue.

Each queue element stores the cell coordinates along with the distance from the source. Since BFS explores all nodes at the current distance before moving to the next level, the first time we reach the destination cell, it gives the minimum number of steps.

We mark cells as visited (set them to 0) to avoid revisiting and ensure each cell is processed only once.

Base Cases:

#include #include #include using namespace std;

int shortestPath(vector<vector> &mat, vector &src, vector &dest) {

int n = mat.size();
int m = mat[0].size();

// Source or destination is blocked
if (mat[src[0]][src[1]] == 0 || mat[dest[0]][dest[1]] == 0)
    return -1;

// Queue stores {cell, distance from source}
queue<pair<pair<int, int>, int>> q;

q.push({{src[0], src[1]}, 0});

// Mark source as visited
mat[src[0]][src[1]] = 0;

// Four possible directions
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};

while (!q.empty())
{

    auto curr = q.front();
    q.pop();

    int x = curr.first.first;
    int y = curr.first.second;
    int dist = curr.second;

    // Destination reached
    if (x == dest[0] && y == dest[1])
        return dist;

    // Explore all four adjacent cells
    for (int i = 0; i < 4; i++)
    {

        int nx = x + dx[i];
        int ny = y + dy[i];

        if (nx >= 0 && nx < n && ny >= 0 && ny < m && mat[nx][ny] == 1)
        {

            // Mark as visited
            mat[nx][ny] = 0;

            q.push({{nx, ny}, dist + 1});
        }
    }
}

// Destination cannot be reached
return -1;

}

int main() {

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

vector<int> src = {0, 1};
vector<int> dest = {2, 2};
cout << shortestPath(mat, src, dest);

return 0;

}

Java

import java.util.Queue; import java.util.LinkedList; import java.util.Arrays;

class GFG {

int shortestPath(int[][] mat, int[] src, int[] dest)
{

    int n = mat.length;
    int m = mat[0].length;

    // Source or destination is blocked
    if (mat[src[0]][src[1]] == 0 || mat[dest[0]][dest[1]] == 0)
        return -1;

    // Queue stores {cell, distance from source}
    Queue<int[]> q = new LinkedList<>();

    q.add(new int[]{src[0], src[1], 0});

    // Mark source as visited
    mat[src[0]][src[1]] = 0;

    // Four possible directions
    int dx[] = {-1, 1, 0, 0};
    int dy[] = {0, 0, -1, 1};

    while (!q.isEmpty())
    {

        int[] curr = q.poll();

        int x = curr[0];
        int y = curr[1];
        int dist = curr[2];

        // Destination reached
        if (x == dest[0] && y == dest[1])
            return dist;

        // Explore all four adjacent cells
        for (int i = 0; i < 4; i++)
        {

            int nx = x + dx[i];
            int ny = y + dy[i];

            if (nx >= 0 && nx < n && ny >= 0 && ny < m && mat[nx][ny] == 1)
            {

                // Mark as visited
                mat[nx][ny] = 0;

                q.add(new int[]{nx, ny, dist + 1});
            }
        }
    }

    // Destination cannot be reached
    return -1;
}

public static void main(String[] args)
{

    int[][] mat = {
        {1, 1, 1, 1},
        {1, 1, 0, 1},
        {1, 1, 1, 1},
        {1, 1, 0, 0},
        {1, 0, 0, 1}
    };

    int[] src = {0, 1};
    int[] dest = {2, 2};

    Solution obj = new Solution();
    System.out.println(obj.shortestPath(mat, src, dest));
}

}

Python

from collections import deque

def shortestPath(mat, src, dest):

n = len(mat)
m = len(mat[0])

# Source or destination is blocked
if mat[src[0]][src[1]] == 0 or mat[dest[0]][dest[1]] == 0:
    return -1

# Queue stores {cell, distance from source}
q = deque()

q.append((src[0], src[1], 0))

# Mark source as visited
mat[src[0]][src[1]] = 0

# Four possible directions
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]

while q:

    x, y, dist = q.popleft()

    # Destination reached
    if x == dest[0] and y == dest[1]:
        return dist

    # Explore all four adjacent cells
    for i in range(4):

        nx = x + dx[i]
        ny = y + dy[i]

        if 0 <= nx < n and 0 <= ny < m and mat[nx][ny] == 1:

            # Mark as visited
            mat[nx][ny] = 0

            q.append((nx, ny, dist + 1))

# Destination cannot be reached
return -1

if name == "main":

mat = [
    [1, 1, 1, 1],
    [1, 1, 0, 1],
    [1, 1, 1, 1],
    [1, 1, 0, 0],
    [1, 0, 0, 1]
]

src = [0, 1]
dest = [2, 2]

print(shortestPath(mat, src, dest))

C#

using System; using System.Collections.Generic;

class GFG { public int shortestPath(int[][] mat, int[] src, int[] dest) {

    int n = mat.Length;
    int m = mat[0].Length;

    // Source or destination is blocked
    if (mat[src[0]][src[1]] == 0 || mat[dest[0]][dest[1]] == 0)
        return -1;

    // Queue stores {cell, distance from source}
    Queue<int[]> q = new Queue<int[]>();

    q.Enqueue(new int[] { src[0], src[1], 0 });

    // Mark source as visited
    mat[src[0]][src[1]] = 0;

    // Four possible directions
    int[] dx = { -1, 1, 0, 0 };
    int[] dy = { 0, 0, -1, 1 };

    while (q.Count > 0)
    {

        int[] curr = q.Dequeue();

        int x = curr[0];
        int y = curr[1];
        int dist = curr[2];

        // Destination reached
        if (x == dest[0] && y == dest[1])
            return dist;

        // Explore all four adjacent cells
        for (int i = 0; i < 4; i++)
        {

            int nx = x + dx[i];
            int ny = y + dy[i];

            if (nx >= 0 && nx < n && ny >= 0 && ny < m && mat[nx][ny] == 1)
            {

                // Mark as visited
                mat[nx][ny] = 0;

                q.Enqueue(new int[] { nx, ny, dist + 1 });
            }
        }
    }

    // Destination cannot be reached
    return -1;
}

public static void Main(string[] args)
{

    int[][] mat = new int[][] {
        new int[] {1, 1, 1, 1},
        new int[] {1, 1, 0, 1},
        new int[] {1, 1, 1, 1},
        new int[] {1, 1, 0, 0},
        new int[] {1, 0, 0, 1}
    };

    int[] src = { 0, 1 };
    int[] dest = { 2, 2 };

    Solution obj = new Solution();
    Console.WriteLine(obj.shortestPath(mat, src, dest));
}

}

JavaScript

function shortestPath(mat, src, dest) {

let n = mat.length;
let m = mat[0].length;

// Source or destination is blocked
if (mat[src[0]][src[1]] === 0 || mat[dest[0]][dest[1]] === 0)
    return -1;

// Queue stores {cell, distance from source}
let q = [];

q.push([src[0], src[1], 0]);

// Mark source as visited
mat[src[0]][src[1]] = 0;

// Four possible directions
let dx = [-1, 1, 0, 0];
let dy = [0, 0, -1, 1];

while (q.length > 0)
{

    let curr = q.shift();

    let x = curr[0];
    let y = curr[1];
    let dist = curr[2];

    // Destination reached
    if (x === dest[0] && y === dest[1])
        return dist;

    // Explore all four adjacent cells
    for (let i = 0; i < 4; i++)
    {

        let nx = x + dx[i];
        let ny = y + dy[i];

        if (
            nx >= 0 && nx < n &&
            ny >= 0 && ny < m &&
            mat[nx][ny] === 1
        )
        {

            // Mark as visited
            mat[nx][ny] = 0;

            q.push([nx, ny, dist + 1]);
        }
    }
}

// Destination cannot be reached
return -1;

}

// Driver code let mat = [ [1, 1, 1, 1], [1, 1, 0, 1], [1, 1, 1, 1], [1, 1, 0, 0], [1, 0, 0, 1] ];

let src = [0, 1]; let dest = [2, 2];

console.log(shortestPath(mat, src, dest));

`