Minimum moves required to come out of a grid safely
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: 2
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:
- Initialize two empty queues fQ and pQ, to store the cellsin which the fire can spread and the person can move to, respectively.
- Initialize a 2D array, say visited[][], to check if the cell (i, j) is already visited by the person or not.
- Enqueue all the side-adjacent cells of the person and mark all the adjacent cells as visited cell.
- Enqueue all the side-adjacent cells of the fire cells into fQ and mark all the side-adjacent cells as burning cells.
- Initialize a variable, say depth, to keep track of the shortest distance between two cells.
- 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.
- 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> |
2
Time Complexity: O(N * M)
Auxiliary Space: O(N * M)
Please Login to comment...