Shortest path in a Binary Maze

• Difficulty Level : Hard
• Last Updated : 09 Jun, 2021

Given a MxN matrix where each element can either be 0 or 1. We need to find the shortest path between a given source cell to a destination cell. The path can only be created out of a cell if its value is 1.
Expected time complexity is O(MN).
For example –

Input:
mat[ROW][COL]  = {{1, 0, 1, 1, 1, 1, 0, 1, 1, 1 },
{1, 0, 1, 0, 1, 1, 1, 0, 1, 1 },
{1, 1, 1, 0, 1, 1, 0, 1, 0, 1 },
{0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
{1, 1, 1, 0, 1, 1, 1, 0, 1, 0 },
{1, 0, 1, 1, 1, 1, 0, 1, 0, 0 },
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{1, 0, 1, 1, 1, 1, 0, 1, 1, 1 },
{1, 1, 0, 0, 0, 0, 1, 0, 0, 1 }};
Source = {0, 0};
Destination = {3, 4};

Output:
Shortest Path is 11

Recommended: Please solve it on “PRACTICE” first, before moving on to the solution.

The idea is inspired from Lee algorithm and uses BFS.

1. We start from the source cell and calls BFS procedure.
2. We maintain a queue to store the coordinates of the matrix and initialize it with the source cell.
3. We also maintain a Boolean array visited of same size as our input matrix and initialize all its elements to false.
1. We LOOP till queue is not empty
2. Dequeue front cell from the queue
3. Return if the destination coordinates have reached.
4. For each of its four adjacent cells, if the value is 1 and they are not visited yet, we enqueue it in the queue and also mark them as visited.

Note that BFS works here because it doesn’t consider a single path at once. It considers all the paths starting from the source and moves ahead one unit in all those paths at the same time which makes sure that the first time when the destination is visited, it is the shortest path.
Below is the implementation of the idea –

C++

 // C++ program to find the shortest path between // a given source cell to a destination cell. #include using namespace std; #define ROW 9 #define COL 10   //To store matrix cell coordinates struct Point {     int x;     int y; };   // A Data Structure for queue used in BFS struct queueNode {     Point pt;  // The coordinates of a cell     int dist;  // cell's distance of from the source };   // check whether given cell (row, col) is a valid // cell or not. bool isValid(int row, int col) {     // return true if row number and column number     // is in range     return (row >= 0) && (row < ROW) &&            (col >= 0) && (col < COL); }   // These arrays are used to get row and column // numbers of 4 neighbours of a given cell int rowNum[] = {-1, 0, 0, 1}; int colNum[] = {0, -1, 1, 0};   // function to find the shortest path between // a given source cell to a destination cell. int BFS(int mat[][COL], Point src, Point dest) {     // check source and destination cell     // of the matrix have value 1     if (!mat[src.x][src.y] || !mat[dest.x][dest.y])         return -1;       bool visited[ROW][COL];     memset(visited, false, sizeof visited);           // Mark the source cell as visited     visited[src.x][src.y] = true;       // Create a queue for BFS     queue q;           // Distance of source cell is 0     queueNode s = {src, 0};     q.push(s);  // Enqueue source cell       // Do a BFS starting from source cell     while (!q.empty())     {         queueNode curr = q.front();         Point pt = curr.pt;           // If we have reached the destination cell,         // we are done         if (pt.x == dest.x && pt.y == dest.y)             return curr.dist;           // Otherwise dequeue the front         // cell in the queue         // and enqueue its adjacent cells         q.pop();           for (int i = 0; i < 4; i++)         {             int row = pt.x + rowNum[i];             int col = pt.y + colNum[i];                           // if adjacent cell is valid, has path and             // not visited yet, enqueue it.             if (isValid(row, col) && mat[row][col] &&                !visited[row][col])             {                 // mark cell as visited and enqueue it                 visited[row][col] = true;                 queueNode Adjcell = { {row, col},                                       curr.dist + 1 };                 q.push(Adjcell);             }         }     }       // Return -1 if destination cannot be reached     return -1; }   // Driver program to test above function int main() {     int mat[ROW][COL] =     {         { 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 },         { 1, 0, 1, 0, 1, 1, 1, 0, 1, 1 },         { 1, 1, 1, 0, 1, 1, 0, 1, 0, 1 },         { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },         { 1, 1, 1, 0, 1, 1, 1, 0, 1, 0 },         { 1, 0, 1, 1, 1, 1, 0, 1, 0, 0 },         { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },         { 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 },         { 1, 1, 0, 0, 0, 0, 1, 0, 0, 1 }     };       Point source = {0, 0};     Point dest = {3, 4};       int dist = BFS(mat, source, dest);       if (dist != -1)         cout << "Shortest Path is " << dist ;     else         cout << "Shortest Path doesn't exist";       return 0; }

Java

 // Java program to find the shortest // path between a given source cell // to a destination cell. import java.util.*;   class GFG { static int ROW = 9; static int COL = 10;   // To store matrix cell coordinates static class Point {     int x;     int y;       public Point(int x, int y)     {         this.x = x;         this.y = y;     } };   // A Data Structure for queue used in BFS static class queueNode {     Point pt; // The coordinates of a cell     int dist; // cell's distance of from the source       public queueNode(Point pt, int dist)     {         this.pt = pt;         this.dist = dist;     } };   // check whether given cell (row, col) // is a valid cell or not. static boolean isValid(int row, int col) {     // return true if row number and     // column number is in range     return (row >= 0) && (row < ROW) &&            (col >= 0) && (col < COL); }   // These arrays are used to get row and column // numbers of 4 neighbours of a given cell static int rowNum[] = {-1, 0, 0, 1}; static int colNum[] = {0, -1, 1, 0};   // function to find the shortest path between // a given source cell to a destination cell. static int BFS(int mat[][], Point src,                             Point dest) {     // check source and destination cell     // of the matrix have value 1     if (mat[src.x][src.y] != 1 ||         mat[dest.x][dest.y] != 1)         return -1;       boolean [][]visited = new boolean[ROW][COL];           // Mark the source cell as visited     visited[src.x][src.y] = true;       // Create a queue for BFS     Queue q = new LinkedList<>();           // Distance of source cell is 0     queueNode s = new queueNode(src, 0);     q.add(s); // Enqueue source cell       // Do a BFS starting from source cell     while (!q.isEmpty())     {         queueNode curr = q.peek();         Point pt = curr.pt;           // If we have reached the destination cell,         // we are done         if (pt.x == dest.x && pt.y == dest.y)             return curr.dist;           // Otherwise dequeue the front cell         // in the queue and enqueue         // its adjacent cells         q.remove();           for (int i = 0; i < 4; i++)         {             int row = pt.x + rowNum[i];             int col = pt.y + colNum[i];                           // if adjacent cell is valid, has path             // and not visited yet, enqueue it.             if (isValid(row, col) &&                     mat[row][col] == 1 &&                     !visited[row][col])             {                 // mark cell as visited and enqueue it                 visited[row][col] = true;                 queueNode Adjcell = new queueNode                              (new Point(row, col),                                    curr.dist + 1 );                 q.add(Adjcell);             }         }     }       // Return -1 if destination cannot be reached     return -1; }   // Driver Code public static void main(String[] args) {     int mat[][] = {{ 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 },                    { 1, 0, 1, 0, 1, 1, 1, 0, 1, 1 },                    { 1, 1, 1, 0, 1, 1, 0, 1, 0, 1 },                    { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },                    { 1, 1, 1, 0, 1, 1, 1, 0, 1, 0 },                    { 1, 0, 1, 1, 1, 1, 0, 1, 0, 0 },                    { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },                    { 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 },                    { 1, 1, 0, 0, 0, 0, 1, 0, 0, 1 }};       Point source = new Point(0, 0);     Point dest = new Point(3, 4);       int dist = BFS(mat, source, dest);       if (dist != -1)         System.out.println("Shortest Path is " + dist);     else         System.out.println("Shortest Path doesn't exist");     } }   // This code is contributed by PrinciRaj1992

Python

 # Python program to find the shortest # path between a given source cell # to a destination cell.   from collections import deque ROW = 9 COL = 10   # To store matrix cell coordinates class Point:     def __init__(self,x: int, y: int):         self.x = x         self.y = y   # A data structure for queue used in BFS class queueNode:     def __init__(self,pt: Point, dist: int):         self.pt = pt  # The coordinates of the cell         self.dist = dist  # Cell's distance from the source   # Check whether given cell(row,col) # is a valid cell or not def isValid(row: int, col: int):     return (row >= 0) and (row < ROW) and                    (col >= 0) and (col < COL)   # These arrays are used to get row and column # numbers of 4 neighbours of a given cell rowNum = [-1, 0, 0, 1] colNum = [0, -1, 1, 0]   # Function to find the shortest path between # a given source cell to a destination cell. def BFS(mat, src: Point, dest: Point):           # check source and destination cell     # of the matrix have value 1     if mat[src.x][src.y]!=1 or mat[dest.x][dest.y]!=1:         return -1           visited = [[False for i in range(COL)]                        for j in range(ROW)]           # Mark the source cell as visited     visited[src.x][src.y] = True           # Create a queue for BFS     q = deque()           # Distance of source cell is 0     s = queueNode(src,0)     q.append(s) #  Enqueue source cell           # Do a BFS starting from source cell     while q:           curr = q.popleft() # Dequeue the front cell                   # If we have reached the destination cell,         # we are done         pt = curr.pt         if pt.x == dest.x and pt.y == dest.y:             return curr.dist                   # Otherwise enqueue its adjacent cells         for i in range(4):             row = pt.x + rowNum[i]             col = pt.y + colNum[i]                           # if adjacent cell is valid, has path              # and not visited yet, enqueue it.             if (isValid(row,col) and                mat[row][col] == 1 and                 not visited[row][col]):                 visited[row][col] = True                 Adjcell = queueNode(Point(row,col),                                     curr.dist+1)                 q.append(Adjcell)           # Return -1 if destination cannot be reached     return -1   # Driver code def main():     mat = [[ 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 ],            [ 1, 0, 1, 0, 1, 1, 1, 0, 1, 1 ],            [ 1, 1, 1, 0, 1, 1, 0, 1, 0, 1 ],            [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],            [ 1, 1, 1, 0, 1, 1, 1, 0, 1, 0 ],            [ 1, 0, 1, 1, 1, 1, 0, 1, 0, 0 ],            [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 ],            [ 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 ],            [ 1, 1, 0, 0, 0, 0, 1, 0, 0, 1 ]]     source = Point(0,0)     dest = Point(3,4)           dist = BFS(mat,source,dest)           if dist!=-1:         print("Shortest Path is",dist)     else:         print("Shortest Path doesn't exist") main()   # This code is contributed by stutipathak31jan

C#

 // C# program to find the shortest // path between a given source cell // to a destination cell. using System; using System.Collections.Generic;   class GFG { static int ROW = 9; static int COL = 10;   // To store matrix cell coordinates public class Point {     public int x;     public int y;       public Point(int x, int y)     {         this.x = x;         this.y = y;     } };   // A Data Structure for queue used in BFS public class queueNode {     // The coordinates of a cell     public Point pt;           // cell's distance of from the source     public int dist;       public queueNode(Point pt, int dist)     {         this.pt = pt;         this.dist = dist;     } };   // check whether given cell (row, col) // is a valid cell or not. static bool isValid(int row, int col) {     // return true if row number and     // column number is in range     return (row >= 0) && (row < ROW) &&            (col >= 0) && (col < COL); }   // These arrays are used to get row and column // numbers of 4 neighbours of a given cell static int []rowNum = {-1, 0, 0, 1}; static int []colNum = {0, -1, 1, 0};   // function to find the shortest path between // a given source cell to a destination cell. static int BFS(int [,]mat, Point src,                            Point dest) {     // check source and destination cell     // of the matrix have value 1     if (mat[src.x, src.y] != 1 ||         mat[dest.x, dest.y] != 1)         return -1;       bool [,]visited = new bool[ROW, COL];           // Mark the source cell as visited     visited[src.x, src.y] = true;       // Create a queue for BFS     Queue q = new Queue();           // Distance of source cell is 0     queueNode s = new queueNode(src, 0);     q.Enqueue(s); // Enqueue source cell       // Do a BFS starting from source cell     while (q.Count != 0)     {         queueNode curr = q.Peek();         Point pt = curr.pt;           // If we have reached the destination cell,         // we are done         if (pt.x == dest.x && pt.y == dest.y)             return curr.dist;           // Otherwise dequeue the front cell         // in the queue and enqueue         // its adjacent cells         q.Dequeue();           for (int i = 0; i < 4; i++)         {             int row = pt.x + rowNum[i];             int col = pt.y + colNum[i];                           // if adjacent cell is valid, has path             // and not visited yet, enqueue it.             if (isValid(row, col) &&                     mat[row, col] == 1 &&                !visited[row, col])             {                 // mark cell as visited and enqueue it                 visited[row, col] = true;                 queueNode Adjcell = new queueNode                            (new Point(row, col),                                 curr.dist + 1 );                 q.Enqueue(Adjcell);             }         }     }       // Return -1 if destination cannot be reached     return -1; }   // Driver Code public static void Main(String[] args) {     int [,]mat = {{ 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 },                   { 1, 0, 1, 0, 1, 1, 1, 0, 1, 1 },                    { 1, 1, 1, 0, 1, 1, 0, 1, 0, 1 },                   { 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },                   { 1, 1, 1, 0, 1, 1, 1, 0, 1, 0 },                   { 1, 0, 1, 1, 1, 1, 0, 1, 0, 0 },                   { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },                   { 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 },                   { 1, 1, 0, 0, 0, 0, 1, 0, 0, 1 }};       Point source = new Point(0, 0);     Point dest = new Point(3, 4);       int dist = BFS(mat, source, dest);       if (dist != -1)         Console.WriteLine("Shortest Path is " + dist);     else         Console.WriteLine("Shortest Path doesn't exist");     } }   // This code is contributed by PrinciRaj1992

Output :

Shortest Path is 11