Open In App

Minimum moves required to come out of a grid safely

Last Updated : 16 Jul, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Given a grid mat[][] of size M * N, consisting of only 0s, 1s, and 2s, where 0 represents empty place, 1 represents a person and 2 represents the fire, the task is to count the minimum number of moves required such that the person comes out from the grid safely. In each step, the fire will burn its side-adjacent cells and the person will move from the current cell to one of its side-adjacent cells. If it is not possible to come out from the grid, then print -1.

Note: A person will come out from the grid if the person reaches one of the border sides of the grid.

Examples:

Input: mat[][] = { { 0, 0, 0, 0 }, { 2, 0, 0, 0 }, { 2, 1, 0, 0 }, { 2, 2, 0, 0 } } 
Output:
Explanation: 
Possible moves of the person are (2, 1) ? (2, 2) ? (2, 3). 
The person reaches one of the border sides of the grid(last row) in 2 moves and also it is the minimum possible count. 
Therefore, the required output is 2.

Input: mat[][] = { { 0, 2, 0, 0 }, { 2, 1, 0, 2 }, { 2, 0, 0, 0 }, { 2, 0, 2, 0 }} 
Output: -1

Approach: The problem can be solved using concepts to solve the problem Rotten Oranges. The idea is to perform BFS on the spreading fire as well as the moves of the person. Follow the steps below to solve the problem:

  1. Initialize two empty queues fQ and pQ, to store the cellsin which the fire can spread and the person can move to, respectively.
  2. Initialize a 2D array, say visited[][], to check if the cell (i, j) is already visited by the person or not.
  3. Enqueue all the side-adjacent cells of the person and mark all the adjacent cells as visited cell.
  4. Enqueue all the side-adjacent cells of the fire cells into fQ and mark all the side-adjacent cells as burning cells.
  5. Initialize a variable, say depth, to keep track of the shortest distance between two cells.
  6. Perform the following steps while pQ is not empty: 
    • Increment the depth by 1.
    • Dequeue all cells from pQ and enqueue all the valid side-adjacent cells of the popped cell.
    • If any adjacent cell enqueued is present at border of the grid, then print the value of depth.
    • Otherwise, dequeue all the cells from fQ. For each popped cell, enqueue all the valid adjacent cells.
  7. From the above steps, if it is not possible to come out from the grid, then print -1.

Below is the implementation of above approach:

C++




// C++ program to implement
// the above approach
 
#include <bits/stdc++.h>
 
using namespace std;
 
// Stores size of the grid
int m, n;
 
// Function to check valid
// cells of the grid
bool valid(int x, int y)
{
    return (x >= 0 && x < m && y >= 0 && y < n);
}
 
// Checks for the border sides
bool border(int x, int y)
{
    return (x == 0 || x == m - 1 || y == 0 || y == n - 1);
}
 
 
// Function to find shortest distance
// between two cells of the grid
int minStep(vector<vector<int>> mat)
{
 
    // Rows of the grid
    m = mat.size();
 
    // Column of the grid
    n = mat[0].size();
 
    // Stores possible move
    // of the person
    int dx[] = { 1, -1, 0, 0 };
    int dy[] = { 0, 0, 1, -1 };
 
    // Store possible cells visited
    // by the person
    queue<pair<int,int> > pQ;
 
    // Store possible cells which
    // are burning
    queue<pair<int,int> > fQ;
 
    // Traverse the grid
    for (int i = 0; i < m; i++){
 
        for (int j = 0; j < n; j++) {
 
            // If current cell is
            // burning
            if (mat[i][j] == 2)
                fQ.push({i, j});
            // If person is in
            // the current cell
            else if (mat[i][j] == 1) {
                if (border(i, j))
                    return 0;
                pQ.push({i, j});
            }
        }
    }
    // Stores shortest distance
    // between two cells
    int depth = 0;
 
    // Check if a cell is visited
    // by the person or not
    vector<vector<int>> visited(n,vector<int>(m,0));
 
    // While pQ is not empty
    while (pQ.size()>0) {
 
        // Update depth
        depth++;
 
        // Popped all the cells from
        // pQ and mark all adjacent cells
        // of as visited
        for (int i = pQ.size(); i > 0;i--) {
 
            // Front element of
            // the queue pQ
            pair<int,int>  pos = pQ.front();
 
            // Remove front element of
            // the queue pQ
            pQ.pop();
 
            // If current cell is burning
            if (mat[pos.first][pos.second] == 2)
                continue;
 
            // Find all adjacent cells
            for (int j = 0; j < 4; j++) {
 
                // Stores row number of
                // adjacent cell
                int x = pos.first + dx[j];
 
                // Stores column number
                // of adjacent cell
                int y = pos.second + dy[j];
 
                // Checks if current cell
                // is valid
                if (valid(x, y) && mat[x][y] != 2 && !visited[x][y]) {
 
                    // Mark the cell as visited
                    visited[x][y] = 1;
 
                    // Enqueue the cell
                    pQ.push(pair<int,int> (x, y));
 
                    // Checks the escape condition
                    if (border(x, y))
                        return depth;
                }
            }
        }
 
        // Burn all the adjacent cells
        // of burning cells
        for (int i = fQ.size(); i > 0; i--) {
 
            // Front element of
            // the queue fQ
            pair<int,int>  pos = fQ.front();
 
            // Delete front element of
            // the queue fQ
            fQ.pop();
 
            // Find adjacent cells of
            // burning cell
            for (int j = 0; j < 4; j++) {
 
                // Stores row number of
                // adjacent cell
                int x = pos.first + dx[j];
 
                // Stores column number
                // of adjacent cell
                int y = pos.second + dy[j];
 
                // Checks if current
                // cell is valid
                if (valid(x, y) && mat[x][y] != 2) {
 
                    mat[x][y] = 2;
 
                    // Burn all the adjacent
                    // cells of current cell
                    fQ.push(pair<int,int> (x, y));
                }
            }
        }
    }
    return -1;
}
 
// Driver Code
int main()
{
 
    // Given grid
    vector<vector<int>> grid = { { 0, 0, 0, 0 },
                     { 2, 0, 0, 0 },
                     { 2, 1, 0, 0 },
                     { 2, 2, 0, 0 } };
 
    cout<<minStep(grid);
}


Java




// Java program to implement
// the above approach
import java.util.*;
import java.lang.*;
class GFG
{
 
    // Structure of cell
    // of the grid
    static class pair
    {
        int x, y;
        pair(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
    }
 
    // Stores size of the grid
    static int m, n;
 
    // Function to find shortest distance
    // between two cells of the grid
    static int minStep(int[][] mat)
    {
 
        // Rows of the grid
        m = mat.length;
 
        // Column of the grid
        n = mat[0].length;
 
        // Stores possible move
        // of the person
        int dx[] = { 1, -1, 0, 0 };
        int dy[] = { 0, 0, 1, -1 };
 
        // Store possible cells visited
        // by the person
        Queue<pair> pQ = new LinkedList<>();
 
        // Store possible cells which
        // are burning
        Queue<pair> fQ = new LinkedList<>();
 
        // Traverse the grid
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
            {
 
                // If current cell is
                // burning
                if (mat[i][j] == 2)
                    fQ.add(new pair(i, j));
 
                // If person is in
                // the current cell
                else if (mat[i][j] == 1)
                {
                    if (border(i, j))
                        return 0;
                    pQ.add(new pair(i, j));
                }
            }
 
        // Stores shortest distance
        // between two cells
        int depth = 0;
 
        // Check if a cell is visited
        // by the person or not
        boolean[][] visited
            = new boolean[n][m];
 
        // While pQ is not empty
        while (!pQ.isEmpty())
        {
 
            // Update depth
            depth++;
 
            // Popped all the cells from
            // pQ and mark all adjacent cells
            // of as visited
            for (int i = pQ.size(); i > 0; i--)
            {
 
                // Front element of
                // the queue pQ
                pair pos = pQ.peek();
 
                // Remove front element of
                // the queue pQ
                pQ.remove();
 
                // If current cell is burning
                if (mat[pos.x][pos.y] == 2)
                    continue;
 
                // Find all adjacent cells
                for (int j = 0; j < 4; j++)
                {
 
                    // Stores row number of
                    // adjacent cell
                    int x = pos.x + dx[j];
 
                    // Stores column number
                    // of adjacent cell
                    int y = pos.y + dy[j];
 
                    // Checks if current cell
                    // is valid
                    if (valid(x, y) && mat[x][y] != 2
                        && !visited[x][y])
                    {
 
                        // Mark the cell as visited
                        visited[x][y] = true;
 
                        // Enqueue the cell
                        pQ.add(new pair(x, y));
 
                        // Checks the escape condition
                        if (border(x, y))
                            return depth;
                    }
                }
            }
 
            // Burn all the adjacent cells
            // of burning cells
            for (int i = fQ.size(); i > 0; i--)
            {
 
                // Front element of
                // the queue fQ
                pair pos = fQ.peek();
 
                // Delete front element of
                // the queue fQ
                fQ.remove();
 
                // Find adjacent cells of
                // burning cell
                for (int j = 0; j < 4; j++)
                {
 
                    // Stores row number of
                    // adjacent cell
                    int x = pos.x + dx[j];
 
                    // Stores column number
                    // of adjacent cell
                    int y = pos.y + dy[j];
 
                    // Checks if current
                    // cell is valid
                    if (valid(x, y) && mat[x][y] != 2)
                    {
 
                        mat[x][y] = 2;
 
                        // Burn all the adjacent
                        // cells of current cell
                        fQ.add(new pair(x, y));
                    }
                }
            }
        }
        return -1;
    }
 
    // Function to check valid
    // cells of the grid
    static boolean valid(int x, int y)
    {
        return (x >= 0 && x < m
                && y >= 0 && y < n);
    }
 
    // Checks for the border sides
    static boolean border(int x, int y)
    {
        return (x == 0 || x == m - 1
                || y == 0 || y == n - 1);
    }
 
    // Driver Code
    public static void main(String[] args)
    {
 
        // Given grid
        int[][] grid = { { 0, 0, 0, 0 },
                         { 2, 0, 0, 0 },
                         { 2, 1, 0, 0 },
                         { 2, 2, 0, 0 } };
 
        System.out.println(minStep(grid));
    }
}
 
// This code is contributed by mohit kumar 29.


Python3




# Python3 program to implement
# the above approach
 
# Stores size of the grid
m = 0
n = 0
 
# Function to check valid
# cells of the grid
def valid(x, y):
     
    global n
    global m
    return (x >= 0 and x < m and
            y >= 0 and y < n)
 
# Checks for the border sides
def border(x, y):
     
    global n
    global m
    return (x == 0 or x == m - 1 or
            y == 0 or y == n - 1)
 
# Function to find shortest distance
# between two cells of the grid
def minStep(mat):
     
    global n
    global m
     
    # Rows of the grid
    m = len(mat)
 
    # Column of the grid
    n = len(mat[0])
 
    # Stores possible move
    # of the person
    dx = [1, -1, 0, 0]
    dy = [0, 0, 1, -1]
 
    # Store possible cells visited
    # by the person
    pQ = []
 
    # Store possible cells which
    # are burning
    fQ = []
 
    # Traverse the grid
    for i in range(m):
        for j in range(n):
             
            # If current cell is
            # burning
            if (mat[i][j] == 2):
                fQ.append([i, j])
                 
            # If person is in
            # the current cell
            elif(mat[i][j] == 1):
                if (border(i, j)):
                    return 0
                     
                pQ.append([i, j])
 
    # Stores shortest distance
    # between two cells
    depth = 0
 
    # Check if a cell is visited
    # by the person or not
    visited = [[0 for i in range(m)]
                  for j in range(n)]
 
    # While pQ is not empty
    while (len(pQ) > 0):
         
        # Update depth
        depth += 1
 
        # Popped all the cells from
        # pQ and mark all adjacent cells
        # of as visited
        i = len(pQ)
         
        while(i > 0):
             
            # Front element of
            # the queue pQ
            pos = pQ[0]
 
            # Remove front element of
            # the queue pQ
            pQ.remove(pQ[0])
 
            # If current cell is burning
            if (mat[pos[0]][pos[1]] == 2):
                continue
 
            # Find all adjacent cells
            for j in range(4):
                 
                # Stores row number of
                # adjacent cell
                x = pos[0] + dx[j]
 
                # Stores column number
                # of adjacent cell
                y = pos[1] + dy[j]
 
                # Checks if current cell
                # is valid
                if (valid(x, y) and mat[x][y] != 2 and
                    visited[x][y] == 0):
 
                    # Mark the cell as visited
                    visited[x][y] = 1
 
                    # Enqueue the cell
                    pQ.append([x, y])
 
                    # Checks the escape condition
                    if (border(x, y)):
                        return depth
                         
            i -= 1
 
        # Burn all the adjacent cells
        # of burning cells
        i = len(fQ)
         
        while(i > 0):
 
            # Front element of
            # the queue fQ
            pos = fQ[0]
 
            # Delete front element of
            # the queue fQ
            fQ.remove(fQ[0])
 
            # Find adjacent cells of
            # burning cell
            for j in range(4):
                 
                # Stores row number of
                # adjacent cell
                x = pos[0] + dx[j]
 
                # Stores column number
                # of adjacent cell
                y = pos[1] + dy[j]
 
                # Checks if current
                # cell is valid
                if (valid(x, y) and mat[x][y] != 2):
                    mat[x][y] = 2
 
                    # Burn all the adjacent
                    # cells of current cell
                    fQ.append([x, y])
                     
            i -= 1
 
    return -1
 
# Driver Code
if __name__ == '__main__':
     
    # Given grid
    grid = [ [ 0, 0, 0, 0 ],
             [ 2, 0, 0, 0 ],
             [ 2, 1, 0, 0 ],
             [ 2, 2, 0, 0 ] ]
 
    print(minStep(grid))
 
# This code is contributed by SURENDRA_GANGWAR


C#




// C# program to implement
// the above approach
using System;
using System.Collections.Generic;
public class GFG
{
 
  // Structure of cell
  // of the grid
  class pair
  {
    public int x, y;
    public pair(int x, int y)
    {
      this.x = x;
      this.y = y;
    }
  }
 
  // Stores size of the grid
  static int m, n;
 
  // Function to find shortest distance
  // between two cells of the grid
  static int minStep(int[,] mat)
  {
 
    // Rows of the grid
    m = mat.GetLength(0);
 
    // Column of the grid
    n = mat.GetLength(1);
 
    // Stores possible move
    // of the person
    int []dx = { 1, -1, 0, 0 };
    int []dy = { 0, 0, 1, -1 };
 
    // Store possible cells visited
    // by the person
    Queue<pair> pQ = new Queue<pair>();
 
    // Store possible cells which
    // are burning
    Queue<pair> fQ = new Queue<pair>();
 
    // Traverse the grid
    for (int i = 0; i < m; i++)
      for (int j = 0; j < n; j++)
      {
 
        // If current cell is
        // burning
        if (mat[i, j] == 2)
          fQ.Enqueue(new pair(i, j));
 
        // If person is in
        // the current cell
        else if (mat[i, j] == 1)
        {
          if (border(i, j))
            return 0;
          pQ.Enqueue(new pair(i, j));
        }
      }
 
    // Stores shortest distance
    // between two cells
    int depth = 0;
 
    // Check if a cell is visited
    // by the person or not
    bool[,] visited
      = new bool[n, m];
 
    // While pQ is not empty
    while (pQ.Count != 0)
    {
 
      // Update depth
      depth++;
 
      // Popped all the cells from
      // pQ and mark all adjacent cells
      // of as visited
      for (int i = pQ.Count; i > 0; i--)
      {
 
        // Front element of
        // the queue pQ
        pair pos = pQ.Peek();
 
        // Remove front element of
        // the queue pQ
        pQ.Dequeue();
 
        // If current cell is burning
        if (mat[pos.x, pos.y] == 2)
          continue;
 
        // Find all adjacent cells
        for (int j = 0; j < 4; j++)
        {
 
          // Stores row number of
          // adjacent cell
          int x = pos.x + dx[j];
 
          // Stores column number
          // of adjacent cell
          int y = pos.y + dy[j];
 
          // Checks if current cell
          // is valid
          if (valid(x, y) && mat[x, y] != 2
              && !visited[x, y])
          {
 
            // Mark the cell as visited
            visited[x, y] = true;
 
            // Enqueue the cell
            pQ.Enqueue(new pair(x, y));
 
            // Checks the escape condition
            if (border(x, y))
              return depth;
          }
        }
      }
 
      // Burn all the adjacent cells
      // of burning cells
      for (int i = fQ.Count; i > 0; i--)
      {
 
        // Front element of
        // the queue fQ
        pair pos = fQ.Peek();
 
        // Delete front element of
        // the queue fQ
        fQ.Dequeue();
 
        // Find adjacent cells of
        // burning cell
        for (int j = 0; j < 4; j++)
        {
 
          // Stores row number of
          // adjacent cell
          int x = pos.x + dx[j];
 
          // Stores column number
          // of adjacent cell
          int y = pos.y + dy[j];
 
          // Checks if current
          // cell is valid
          if (valid(x, y) && mat[x, y] != 2)
          {
 
            mat[x, y] = 2;
 
            // Burn all the adjacent
            // cells of current cell
            fQ.Enqueue(new pair(x, y));
          }
        }
      }
    }
    return -1;
  }
 
  // Function to check valid
  // cells of the grid
  static bool valid(int x, int y)
  {
    return (x >= 0 && x < m
            && y >= 0 && y < n);
  }
 
  // Checks for the border sides
  static bool border(int x, int y)
  {
    return (x == 0 || x == m - 1
            || y == 0 || y == n - 1);
  }
 
  // Driver Code
  public static void Main(String[] args)
  {
 
    // Given grid
    int[,] grid = { { 0, 0, 0, 0 },
                   { 2, 0, 0, 0 },
                   { 2, 1, 0, 0 },
                   { 2, 2, 0, 0 } };
 
    Console.WriteLine(minStep(grid));
  }
}
 
// This code is contributed by shikhasingrajput


Javascript




<script>
 
 
// Javascript program to implement
// the above approach
 
// Stores size of the grid
var m, n;
 
// Function to check valid
// cells of the grid
function valid(x, y)
{
    return (x >= 0 && x < m && y >= 0 && y < n);
}
 
// Checks for the border sides
function border(x, y)
{
    return (x == 0 || x == m - 1 || y == 0 || y == n - 1);
}
 
 
// Function to find shortest distance
// between two cells of the grid
function minStep(mat)
{
 
    // Rows of the grid
    m = mat.length;
 
    // Column of the grid
    n = mat[0].length;
 
    // Stores possible move
    // of the person
    var dx = [1, -1, 0, 0];
    var dy = [0, 0, 1, -1];
 
    // Store possible cells visited
    // by the person
    var pQ = [];
 
    // Store possible cells which
    // are burning
    var fQ = [];
 
    // Traverse the grid
    for (var i = 0; i < m; i++){
 
        for (var j = 0; j < n; j++) {
 
            // If current cell is
            // burning
            if (mat[i][j] == 2)
                fQ.push([i, j]);
            // If person is in
            // the current cell
            else if (mat[i][j] == 1) {
                if (border(i, j))
                    return 0;
                pQ.push([i, j]);
            }
        }
    }
    // Stores shortest distance
    // between two cells
    var depth = 0;
 
    // Check if a cell is visited
    // by the person or not
    var visited = Array.from(Array(n), ()=> Array(m).fill(0));
 
    // While pQ is not empty
    while (pQ.length>0) {
 
        // Update depth
        depth++;
 
        // Popped all the cells from
        // pQ and mark all adjacent cells
        // of as visited
        for (var i = pQ.length; i > 0;i--) {
 
            // Front element of
            // the queue pQ
            var pos = pQ[0];
          // Remove front element of
            // the queue pQ
            pQ.shift();
 
            // If current cell is burning
            if (mat[pos[0]][pos[1]] == 2)
                continue;
 
            // Find all adjacent cells
            for (var j = 0; j < 4; j++) {
 
                // Stores row number of
                // adjacent cell
                var x = pos[0] + dx[j];
 
                // Stores column number
                // of adjacent cell
                var y = pos[1] + dy[j];
 
                // Checks if current cell
                // is valid
                if (valid(x, y) && mat[x][y] != 2 && !visited[x][y]) {
 
                    // Mark the cell as visited
                    visited[x][y] = 1;
 
                    // Enqueue the cell
                    pQ.push([x, y]);
 
                    // Checks the escape condition
                    if (border(x, y))
                        return depth;
                }
            }
        }
 
        // Burn all the adjacent cells
        // of burning cells
        for (var i = fQ.length; i > 0; i--) {
 
            // Front element of
            // the queue fQ
            var pos = fQ[0];
 
            // Delete front element of
            // the queue fQ
            fQ.shift();
 
            // Find adjacent cells of
            // burning cell
            for (var j = 0; j < 4; j++) {
 
                // Stores row number of
                // adjacent cell
                var x = pos[0] + dx[j];
 
                // Stores column number
                // of adjacent cell
                var y = pos[1] + dy[j];
 
                // Checks if current
                // cell is valid
                if (valid(x, y) && mat[x][y] != 2) {
 
                    mat[x][y] = 2;
 
                    // Burn all the adjacent
                    // cells of current cell
                    fQ.push([x, y]);
                }
            }
        }
    }
    return -1;
}
 
// Driver Code
// Given grid
var grid = [ [ 0, 0, 0, 0 ],
                 [ 2, 0, 0, 0 ],
                 [ 2, 1, 0, 0 ],
                 [ 2, 2, 0, 0 ] ];
document.write( minStep(grid));
 
// This code is contributed by rutvik_56.
</script>


Output: 

2

 

Time Complexity: O(N * M)
Auxiliary Space: O(N * M)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads