Maze With N doors and 1 Key - GeeksforGeeks

04 May, 2022
Given an N * N binary maze where a 0 denotes that the position can be visited and a 1 denotes that the position cannot be visited without a key, the task is to find whether it is possible to visit the bottom-right cell from the top-left cell with only one key along the way. If possible then print “Yes” else print “No”.
Example: 
Input: maze[][] = { {0, 0, 1}, {1, 0, 1}, {1, 1, 0}} Output: Yes  
Approach: This problem can be solved using recursion, for every possible move, if the current cell is 0 then without altering the status of the key check whether it is the destination else move forward. If the current cell is 1 then the key must be used, now for the further moves the key will be set to false i.e. it’ll never be used again on the same path. If any path reaches the destination then print Yes else print No.
Below is the implementation of the above approach: 
C++
Java
Python3
C#
Javascript
// C++ implementation of the approach#include <bits/stdc++.h>using namespace std; // Recursive function to check whether there is// a path from the top left cell to the// bottom right cell of the mazebool findPath(vector<vector<int> > maze, int xpos, int ypos,              bool key){     // Check whether the current cell is    // within the maze    if (xpos < 0 || xpos >= maze.size() || ypos < 0        || ypos >= maze.size())        return false;     // If key is required to move further    if (maze[xpos][ypos] == '1') {         // If the key hasn't been used before        if (key == true)             // If current cell is the destination            if (xpos == maze.size() - 1                && ypos == maze.size() - 1)                return true;         // Either go down or right        return findPath(maze, xpos + 1, ypos, false)               || findPath(maze, xpos, ypos + 1, false);         // Key has been used before        return false;    }     // If current cell is the destination    if (xpos == maze.size() - 1 && ypos == maze.size() - 1)        return true;     // Either go down or right    return findPath(maze, xpos + 1, ypos, key)           || findPath(maze, xpos, ypos + 1, key);} bool mazeProb(vector<vector<int> > maze, int xpos, int ypos){    bool key = true;    if (findPath(maze, xpos, ypos, key))        return true;     return false;} // Driver codeint main(){    vector<vector<int> > maze = { { '0', '0', '1' },                                  { '1', '0', '1' },                                  { '1', '1', '0' } };    int n = maze.size();     // If there is a path from the cell (0, 0)    if (mazeProb(maze, 0, 0))        cout << "Yes";    else        cout << "No";} // This code is contributed by grand_master
// Java implementation of the approachimport java.io.*;import java.util.ArrayList; class GFG {     // Recursive function to check whether there    // is a path from the top left cell to the    // bottom right cell of the maze    static boolean    findPath(ArrayList<ArrayList<Integer> > maze, int xpos,             int ypos, boolean key)    {         // Check whether the current cell is        // within the maze        if (xpos < 0 || xpos >= maze.size() || ypos < 0            || ypos >= maze.size())            return false;         // If key is required to move further        if (maze.get(xpos).get(ypos) == '1') {             // If the key hasn't been used before            if (key == true)                 // If current cell is the destination                if (xpos == maze.size() - 1                    && ypos == maze.size() - 1)                    return true;             // Either go down or right            return findPath(maze, xpos + 1, ypos, false)                || findPath(maze, xpos, ypos + 1, false);        }         // If current cell is the destination        if (xpos == maze.size() - 1            && ypos == maze.size() - 1)            return true;         // Either go down or right        return findPath(maze, xpos + 1, ypos, key)            || findPath(maze, xpos, ypos + 1, key);    }     static boolean    mazeProb(ArrayList<ArrayList<Integer> > maze, int xpos,             int ypos)    {        boolean key = true;         if (findPath(maze, xpos, ypos, key))            return true;         return false;    }     // Driver code    public static void main(String[] args)    {        int size = 3;        ArrayList<ArrayList<Integer> > maze            = new ArrayList<ArrayList<Integer> >(size);         for (int i = 0; i < size; i++) {            maze.add(new ArrayList<Integer>());        }         // We are making these        //{ { '0', '0', '1' },        //  { '1', '0', '1' },        //  { '1', '1', '0' } };        maze.get(0).add(0);        maze.get(0).add(0);        maze.get(0).add(1);        maze.get(1).add(1);        maze.get(1).add(0);        maze.get(1).add(1);        maze.get(2).add(1);        maze.get(2).add(1);        maze.get(2).add(0);         // If there is a path from the cell (0, 0)        if (mazeProb(maze, 0, 0))            System.out.print("Yes");        else            System.out.print("No");    }} // This code is contributed by sujitmeshram
# Python3 implementation of the approach # Recursive function to check whether there is# a path from the top left cell to the# bottom right cell of the maze  def findPath(maze, xpos, ypos, key):     # Check whether the current cell is    # within the maze    if xpos < 0 or xpos >= len(maze) or ypos < 0 \            or ypos >= len(maze):        return False     # If key is required to move further    if maze[xpos][ypos] == '1':         # If the key hasn't been used before        if key == True:             # If current cell is the destination            if xpos == len(maze)-1 and ypos == len(maze)-1:                return True             # Either go down or right            return findPath(maze, xpos + 1, ypos, False) or \                findPath(maze, xpos, ypos + 1, False)         # Key has been used before        return False     # If current cell is the destination    if xpos == len(maze)-1 and ypos == len(maze)-1:        return True     # Either go down or right    return findPath(maze, xpos + 1, ypos, key) or \        findPath(maze, xpos, ypos + 1, key)  def mazeProb(maze, xpos, ypos):    key = True    if findPath(maze, xpos, ypos, key):        return True    return False  # Driver codeif __name__ == "__main__":     maze = [['0', '0', '1'],            ['1', '0', '1'],            ['1', '1', '0']]    n = len(maze)     # If there is a path from the cell (0, 0)    if mazeProb(maze, 0, 0):        print("Yes")    else:        print("No")
// C# implementation of the approachusing System;using System.Collections.Generic; class GFG {     // Recursive function to check whether there    // is a path from the top left cell to the    // bottom right cell of the maze    static bool findPath(List<List<int> > maze, int xpos,                         int ypos, bool key)    {         // Check whether the current cell is        // within the maze        if (xpos < 0 || xpos >= maze.Count || ypos < 0            || ypos >= maze.Count)            return false;         // If key is required to move further        if (maze[xpos][ypos] == '1') {             // If the key hasn't been used before            if (key == true)                 // If current cell is the destination                if (xpos == maze.Count - 1                    && ypos == maze.Count - 1)                    return true;             // Either go down or right            return findPath(maze, xpos + 1, ypos, false)                || findPath(maze, xpos, ypos + 1, false);        }         // If current cell is the destination        if (xpos == maze.Count - 1            && ypos == maze.Count - 1)            return true;         // Either go down or right        return findPath(maze, xpos + 1, ypos, key)            || findPath(maze, xpos, ypos + 1, key);    }     static bool mazeProb(List<List<int> > maze, int xpos,                         int ypos)    {        bool key = true;         if (findPath(maze, xpos, ypos, key))            return true;         return false;    }     // Driver code    public static void Main(String[] args)    {        int size = 3;        List<List<int> > maze = new List<List<int> >(size);         for (int i = 0; i < size; i++) {            maze.Add(new List<int>());        }         // We are making these        //{ { '0', '0', '1' },        //  { '1', '0', '1' },        //  { '1', '1', '0' } };        maze[0].Add(0);        maze[0].Add(0);        maze[0].Add(1);        maze[1].Add(1);        maze[1].Add(0);        maze[1].Add(1);        maze[2].Add(1);        maze[2].Add(1);        maze[2].Add(0);         // If there is a path from the cell (0, 0)        if (mazeProb(maze, 0, 0))            Console.Write("Yes");        else            Console.Write("No");    }} // This code is contributed by gauravrajput1
<script> // JavaScript implementation of the approach // Recursive function to check whether there is // a path from the top left cell to the // bottom right cell of the mazefunction findPath(maze, xpos, ypos, key){         // Check whether the current cell is    // within the maze    if (xpos < 0 || xpos >= maze.length ||        ypos < 0 || ypos >= maze.length)        return false;     // If key is required to move further    if (maze[xpos][ypos] == '1')    {                 // If the key hasn't been used before        if (key == true)             // If current cell is the destination            if (xpos == maze.length - 1 &&                ypos == maze.length - 1)                return true;         // Either go down or right        return findPath(maze, xpos + 1,                        ypos, false) ||               findPath(maze, xpos,                        ypos + 1, false);         // Key has been used before        return false;    }         // If current cell is the destination    if (xpos == maze.length - 1 &&        ypos == maze.length - 1)        return true;     // Either go down or right    return findPath(maze, xpos + 1,                    ypos, key) ||           findPath(maze, xpos,                    ypos + 1, key);} function mazeProb(maze, xpos, ypos){    let key = true;    if (findPath(maze, xpos, ypos, key))        return true;             return false;} // Driver code    let maze = [ [ '0', '0', '1' ],                 [ '1', '0', '1' ],                 [ '1', '1', '0' ] ];    let n = maze.length;     // If there is a path from the cell (0, 0)    if (mazeProb(maze, 0, 0))        document.write("Yes");    else        document.write("No");         </script>
Yes
Time Complexity: O(2N) 
Dynamic Programming can be used to improve the time complexitiy
The main idea is for every cell the answer is dependented upon its previous row and col .
 
Here maze[1][1] is dependent on maze[1][0] or maze[0][1] if it is a possible path . 
Hence using this approach we can compute result of maze[n-1][n-1] from its previous adjacent cells
And also there are some edge condition for 0th row and 0th col as the these cells are dependent on their previous col and row respectively.
Bellow is the implementation of above approach.
C++
Python3
Javascript
// C++ implementation of the approach#include <bits/stdc++.h>using namespace std; bool mazeProb(vector<vector<int> > maze, int n){     for (int row = 0; row < n; ++row) {        for (int col = 0; col < n; ++col) {             if (row == 0 && col == 0) // Skip the first cell                continue;            if (row == 0) {              // for first row result depend on previous col                maze[row][col] = min(                    2, maze[row][col] + maze[row][col - 1]);            }            else if (col == 0) {              // for first col result depends on previous row                maze[row][col] = min(                    2, maze[row][col] + maze[row - 1][col]);            }            else {              // for other cells, result will be              // minimum of previous row or col cell                maze[row][col]                    = min(2, maze[row][col]                                 + min(maze[row][col - 1],                                       maze[row - 1][col]));            }        }    }     return maze[n - 1][n - 1]           != 2; // if last cell value is 2 then there is no                 // path available} // Driver codeint main(){    vector<vector<int> > maze        = { { 0, 0, 1 }, { 1, 0, 1 }, { 1, 1, 0 } };    int n = maze.size();     // If there is a path from the cell (0, 0)    if (mazeProb(maze, 3))        cout << "Yes";    else        cout << "No";} // This code is contributed by pratham sonawane
# Python implementation of the approachdef mazeProb(maze, n):     for row in range(n):        for col in range(n):             if (row == 0 and col == 0): # Skip the first cell                continue            if (row == 0):              # for first row result depend on previous col                maze[row][col] = min(                    2, maze[row][col] + maze[row][col - 1])            elif (col == 0):              # for first col result depends on previous row                maze[row][col] = min(                    2, maze[row][col] + maze[row - 1][col])            else:              # for other cells, result will be              # minimum of previous row or col cell                maze[row][col]  = min(2, maze[row][col]  + min(maze[row][col - 1], maze[row - 1][col]))     return maze[n - 1][n - 1]!= 2 # if last cell value is 2 then there is no                 # path available # Driver codemaze = [ [ 0, 0, 1 ], [ 1, 0, 1 ], [ 1, 1, 0 ] ]n = len(maze) # If there is a path from the cell (0, 0)if (mazeProb(maze, 3)):    print("Yes")else:    print("No") # This code is contributed by shinjanpatra
<script> // JavaScript implementation of the approachfunction mazeProb(maze,n){     for (let row = 0; row < n; ++row) {        for (let col = 0; col < n; ++col) {             if (row == 0 && col == 0) // Skip the first cell                continue;            if (row == 0) {              // for first row result depend on previous col                maze[row][col] = Math.min(                    2, maze[row][col] + maze[row][col - 1]);            }            else if (col == 0) {              // for first col result depends on previous row                maze[row][col] = Math.min(                    2, maze[row][col] + maze[row - 1][col]);            }            else {              // for other cells, result will be              // minimum of previous row or col cell                maze[row][col]                    = Math.min(2, maze[row][col]                                 + Math.min(maze[row][col - 1],                                       maze[row - 1][col]));            }        }    }     return maze[n - 1][n - 1]!= 2; // if last cell value is 2 then there is no                 // path available} // Driver code let maze = [ [ 0, 0, 1 ], [ 1, 0, 1 ], [ 1, 1, 0 ] ];let n = maze.length; // If there is a path from the cell (0, 0)if (mazeProb(maze, 3))    document.write("Yes");else    document.write("No"); // This code is contributed by shinjanpatra </script>
Yes
Time Complexity: O(N^2)
Space Complexity: O(1)
Akanksha_Rai
grand_master
sujitmeshram
GauravRajput1
rishavmahato348
prathams1001
shinjanpatra
binary-representation
Backtracking
Dynamic Programming
Matrix
Recursion
Dynamic Programming
Recursion
Matrix
Backtracking
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Difference between Backtracking and Branch-N-Bound technique
Find if there is a path of more than k length from a source
Tug of War
Minimum Cost Path in a directed graph via given set of intermediate nodes
Longest common subarray in the given two arrays
0-1 Knapsack Problem | DP-10
Largest Sum Contiguous Subarray
Program for Fibonacci numbers
Longest Common Subsequence | DP-4
Bellman–Ford Algorithm | DP-23