Open In App

Maze With N doors and 1 Key

Improve
Improve
Like Article
Like
Save
Share
Report

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++




// 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 maze
bool 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 code
int 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




// Java implementation of the approach
import 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




# 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 code
if __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#




// C# implementation of the approach
using 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


Javascript




<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 maze
function 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>


Output

Yes

Time Complexity: O(2N)
 

Optimized Approach:

Dynamic Programming can be used to improve the time complexity

The main idea is for every cell the answer is dependent 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.

Below is the implementation of above approach.

C++




// 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 code
int 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


Java




// Java implementation of the approach
 
import java.util.ArrayList;
 
public class GFG {
    static boolean mazeProb(ArrayList<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.get(row)[col] = Math.min(
                        2, maze.get(row)[col]
                               + maze.get(row)[col - 1]);
                }
                else if (col == 0) {
                    // for first col result depends on
                    // previous row
                    maze.get(row)[col] = Math.min(
                        2, maze.get(row)[col]
                               + maze.get(row - 1)[col]);
                }
                else {
                    // for other cells, result will be
                    // minimum of previous row or col cell
                    maze.get(row)[col] = Math.min(
                        2, maze.get(row)[col]
                               + Math.min(
                                   maze.get(row)[col - 1],
                                   maze.get(row - 1)[col]));
                }
            }
        }
 
        return maze.get(n - 1)[n - 1]
            != 2; // if last cell value is 2 then there is
                  // no path available
    }
 
    // Driver code
    public static void main(String[] args)
    {
        ArrayList<int[]> maze = new ArrayList<int[]>();
        maze.add(new int[] { 0, 0, 1 });
        maze.add(new int[] { 1, 0, 1 });
        maze.add(new int[] { 1, 1, 0 });
 
        int n = maze.size();
 
        // If there is a path from the cell (0, 0)
        if (mazeProb(maze, 3))
            System.out.println("Yes");
        else
            System.out.println("No");
    }
}
 
// This code is contributed by Lovely Jain


Python3




# Python implementation of the approach
def 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 code
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, 3)):
    print("Yes")
else:
    print("No")
 
# This code is contributed by shinjanpatra


C#




//C# code for the above approach
using System;
using System.Collections.Generic;
 
class GFG {
  static bool mazeProb(List<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] = 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
  public static void Main()
  {
    List<int[]> maze = new List<int[]>();
    maze.Add(new int[] { 0, 0, 1 });
    maze.Add(new int[] { 1, 0, 1 });
    maze.Add(new int[] { 1, 1, 0 });
 
    int n = maze.Count;
 
    // If there is a path from the cell (0, 0)
    if (mazeProb(maze, 3))
      Console.WriteLine("Yes");
    else
      Console.WriteLine("No");
  }
}
 
// This code is contributed by pradeepkumarppk2003


Javascript




<script>
 
// JavaScript implementation of the approach
function 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>


Output

Yes

Time Complexity: O(N^2)

Space Complexity: O(1)



Last Updated : 03 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads