Given a binary 2D matrix maze[][] of size N X N such that a cell (r, c) is blocked if maze[r] = 0 and unblocked if maze[r] = 1, the task is to start from cell (0, 0) to reach (N – 1, N – 1) by minimizing the number of turns. We can take any of the four directions (Up, Left, Right, Down) as the starting direction. Then, from each cell, we can either move forward one cell in the current direction or turn left or right by 90 degrees. Return -1 if it is impossible to reach the cell (N-1, N-1).
Note: We can only travel through the cells which are unblocked.
Examples:
Input: N = 3, maze[][] = {{1, 1}, {1, 1}}
Output: 1
Explanation: We can take the initial direction as right and continue moving till we reach the second column, after which we take a turn and start moving downwards till we reach cell (N-1, N-1).Input: N = 3, maze[][] = {{1, 0, 1}, {1, 1, 0}, {0, 1, 1}}
Output: 3
Explanation: Three turns are needed to reach the cell (N-1, N-1) from cell (0, 0)
Approach: The problem can be solved using the following approach:
The problem can be solved using 0-1 BFS. We can take all the four directions (Up, Left, Right and Down) as the initial direction and then start moving in that direction. Now, if we are at any cell (i, j), then the cost of moving to a cell in the same direction is 0 and in any other direction is 1. So, we can use this observation to push all the adjacent cells with cost 0 to the front of the deque and all the other adjacent cells to the back of the deque and minimize the number of turns needed to reach cell (N-1, N-1).
Steps to solve the problem:
- Initialize a deque dq to store the current cell with its current direction.
- Create a 2D vector dist[][] to store the minimum number of turns to reach a cell.
- Push the starting cell (0, 0) and its initial direction (0) to the deque.
- Pop a cell from the deque.
- For each valid and unblocked neighbor of the popped cell, check if moving to that neighbor is optimal by checking the dist[][] vector.
- If moving to the neighbor is optimal, update the minimum number of turns to reach that neighbor and push the neighbor to the front if the neighbor is in the same direction else push it to the back of queue.
- Return the minimum number of turns to reach the destination cell.
Below is the implementation of the above approach:
#include <bits/stdc++.h> #define ll long long #define MOD 1000000007 using namespace std;
// Method to check where the cell (r, c) is inside the grid bool isValid( int r, int c, int N)
{ return r >= 0 && c >= 0 && r < N && c < N;
} // Method to find the minimum number of turns with given // initialDirection using 0-1 BFS int solve(vector<vector< int > >& maze, int initialDirection,
vector<pair< int , int > > directions, int N)
{ // Deque to store current cell with current direction
deque<vector< int > > dq;
dq.push_back({ 0, 0, initialDirection });
// 2D vector to store the minimum number of turns to
// reach a cell
vector<vector< int > > dist(N, vector< int >(N, 1e9));
dist[0][0] = 0;
while (!dq.empty()) {
vector< int > ele = dq.front();
dq.pop_front();
int r = ele[0];
int c = ele[1];
int currentDirection = ele[2];
for ( int i = 0; i < 4; i++) {
int nr = r + directions[i].first,
nc = c + directions[i].second;
// Check if the adjacent cell is valid and
// unblocked
if (isValid(nr, nc, N) && maze[nr][nc]) {
int cost = (i == currentDirection ? 0 : 1);
// Check if moving to this cell is optimal
// or not
if (dist[nr][nc] > dist[r] + cost) {
dist[nr][nc] = dist[r] + cost;
// If the adjacent cell is in the same
// direction as the previous one. then
// push the cell to the front
if (cost == 0) {
dq.push_front({ nr, nc, i });
}
// If the adjacent cell is not in the
// same direction as the previous one,
// then push the cell to the back
else {
dq.push_back({ nr, nc, i });
}
}
}
}
}
return dist[N - 1][N - 1];
} // Method to find the minimum number of turns int minimumTurns( int N, vector<vector< int > >& maze)
{ // vector to move to an adjacent cell
vector<pair< int , int > > directions{
{ 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 }
};
// Explore all the four directions as initial direction
int res = min({ solve(maze, 0, directions, N),
solve(maze, 1, directions, N),
solve(maze, 2, directions, N),
solve(maze, 3, directions, N) });
return res == 1e9 ? -1 : res;
} int main()
{ // Input
int N = 3;
vector<vector< int > > maze
= { { 1, 0, 1 }, { 1, 1, 0 }, { 0, 1, 1 } };
cout << minimumTurns(N, maze) << "\n" ;
return 0;
} |
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
public class MinTurns {
// Method to check if the cell (r, c) is inside the grid
static boolean isValid( int r, int c, int N) {
return r >= 0 && c >= 0 && r < N && c < N;
}
// Method to find the minimum number of turns with given
// initialDirection using 0-1 BFS
static int solve( int [][] maze, int initialDirection,
int [][] directions, int N) {
// Deque to store the current cell with the current direction
Deque< int []> dq = new ArrayDeque<>();
dq.add( new int []{ 0 , 0 , initialDirection});
// 2D array to store the minimum number of turns to reach a cell
int [][] dist = new int [N][N];
for ( int [] row : dist) {
Arrays.fill(row, Integer.MAX_VALUE);
}
dist[ 0 ][ 0 ] = 0 ;
while (!dq.isEmpty()) {
int [] ele = dq.pollFirst();
int r = ele[ 0 ];
int c = ele[ 1 ];
int currentDirection = ele[ 2 ];
for ( int i = 0 ; i < 4 ; i++) {
int nr = r + directions[i][ 0 ];
int nc = c + directions[i][ 1 ];
// Check if the adjacent cell is valid and unblocked
if (isValid(nr, nc, N) && maze[nr][nc] == 1 ) {
int cost = (i == currentDirection ? 0 : 1 );
// Check if moving to this cell is optimal or not
if (dist[nr][nc] > dist[r] + cost) {
dist[nr][nc] = dist[r] + cost;
// If the adjacent cell is in the same direction as the previous one,
// then push the cell to the front
if (cost == 0 ) {
dq.addFirst( new int []{nr, nc, i});
}
// If the adjacent cell is not in the same direction as the previous one,
// then push the cell to the back
else {
dq.addLast( new int []{nr, nc, i});
}
}
}
}
}
return dist[N - 1 ][N - 1 ];
}
// Method to find the minimum number of turns
static int minimumTurns( int N, int [][] maze) {
// Array to move to an adjacent cell
int [][] directions = {
{ 0 , 1 }, { 1 , 0 }, { 0 , - 1 }, {- 1 , 0 }
};
// Explore all four directions as the initial direction
int res = Math.min(Math.min(
solve(maze, 0 , directions, N),
solve(maze, 1 , directions, N)),
Math.min(
solve(maze, 2 , directions, N),
solve(maze, 3 , directions, N)
)
);
return res == Integer.MAX_VALUE ? - 1 : res;
}
public static void main(String[] args) {
// Input
int N = 3 ;
int [][] maze = {
{ 1 , 0 , 1 },
{ 1 , 1 , 0 },
{ 0 , 1 , 1 }
};
System.out.println(minimumTurns(N, maze));
}
} // This code is contributed by shivamgupta0987654321 |
from collections import deque
# Method to check if the cell (r, c) is inside the grid def is_valid(r, c, N):
return 0 < = r < N and 0 < = c < N
# Method to find the minimum number of turns with given # initialDirection using 0-1 BFS def solve(maze, initial_direction, directions, N):
# Deque to store the current cell with the current direction
dq = deque([( 0 , 0 , initial_direction)])
# 2D list to store the minimum number of turns to reach a cell
dist = [[ float ( 'inf' )] * N for _ in range (N)]
dist[ 0 ][ 0 ] = 0
while dq:
r, c, current_direction = dq.popleft()
for i in range ( 4 ):
nr, nc = r + directions[i][ 0 ], c + directions[i][ 1 ]
# Check if the adjacent cell is valid and unblocked
if is_valid(nr, nc, N) and maze[nr][nc]:
cost = 0 if i = = current_direction else 1
# Check if moving to this cell is optimal or not
if dist[nr][nc] > dist[r] + cost:
dist[nr][nc] = dist[r] + cost
# If the adjacent cell is in the same
# direction as the previous one, then
# append the cell to the left
if cost = = 0 :
dq.appendleft((nr, nc, i))
# If the adjacent cell is not in the
# same direction as the previous one,
# then append the cell to the right
else :
dq.append((nr, nc, i))
return dist[N - 1 ][N - 1 ]
# Method to find the minimum number of turns def minimum_turns(N, maze):
# List to move to an adjacent cell
directions = [( 0 , 1 ), ( 1 , 0 ), ( 0 , - 1 ), ( - 1 , 0 )]
# Explore all four directions as the initial direction
res = min (solve(maze, i, directions, N) for i in range ( 4 ))
return - 1 if res = = float ( 'inf' ) else res
if __name__ = = "__main__" :
# Input
N = 3
maze = [
[ 1 , 0 , 1 ],
[ 1 , 1 , 0 ],
[ 0 , 1 , 1 ]
]
print (minimum_turns(N, maze))
|
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{ // Method to check if cell (r, c) is inside the grid
static bool IsValid( int r, int c, int N)
{
return r >= 0 && c >= 0 && r < N && c < N;
}
// Method to find the minimum number of turns with given initialDirection using 0-1 BFS
static int Solve(List<List< int >> maze, int initialDirection, List<Tuple< int , int >> directions, int N)
{
Queue<List< int >> dq = new Queue<List< int >>();
dq.Enqueue( new List< int > { 0, 0, initialDirection });
int [,] dist = new int [N, N];
for ( int i = 0; i < N; i++)
{
for ( int j = 0; j < N; j++)
{
dist[i, j] = int .MaxValue;
}
}
dist[0, 0] = 0;
while (dq.Count > 0)
{
List< int > ele = dq.Dequeue();
int r = ele[0];
int c = ele[1];
int currentDirection = ele[2];
for ( int i = 0; i < 4; i++)
{
int nr = r + directions[i].Item1;
int nc = c + directions[i].Item2;
if (IsValid(nr, nc, N) && maze[nr][nc] == 1)
{
int cost = (i == currentDirection) ? 0 : 1;
if (dist[nr, nc] > dist[r, c] + cost)
{
dist[nr, nc] = dist[r, c] + cost;
if (cost == 0)
{
dq.Enqueue( new List< int > { nr, nc, i });
}
else
{
dq.Enqueue( new List< int > { nr, nc, i });
}
}
}
}
}
return dist[N - 1, N - 1];
}
// Method to find the minimum number of turns
static int MinimumTurns( int N, List<List< int >> maze)
{
List<Tuple< int , int >> directions = new List<Tuple< int , int >>
{
Tuple.Create(0, 1), Tuple.Create(1, 0), Tuple.Create(0, -1), Tuple.Create(-1, 0)
};
int res = new int []
{
Solve(maze, 0, directions, N),
Solve(maze, 1, directions, N),
Solve(maze, 2, directions, N),
Solve(maze, 3, directions, N)
}.Min();
return res == int .MaxValue ? -1 : res;
}
static void Main()
{
// Input
int N = 3;
List<List< int >> maze = new List<List< int >>
{
new List< int > { 1, 0, 1 },
new List< int > { 1, 1, 0 },
new List< int > { 0, 1, 1 }
};
Console.WriteLine(MinimumTurns(N, maze));
}
} // This code is contributed by shivamgupta0987654321 |
// JavaScript Implementation of the given problem // Method to check if the cell (r, c) // is inside the grid function isValid(r, c, N) {
return r >= 0 && c >= 0 && r < N && c < N;
} // Method to find the minimum number of // turns with given initialDirection using 0-1 BFS function solve(maze, initialDirection, directions, N) {
// Deque to store current cell
// with current direction
let dq = [[0, 0, initialDirection]];
// 2D array to store minimum number
// of turns to reach a cell
let dist = new Array(N).fill( null ).map(() => new Array(N).fill(1e9));
dist[0][0] = 0;
while (dq.length > 0) {
let [r, c, currentDirection] = dq.shift();
for (let i = 0; i < 4; i++) {
let nr = r + directions[i][0];
let nc = c + directions[i][1];
// Check if the adjacent cell is valid and unblocked
if (isValid(nr, nc, N) && maze[nr][nc]) {
let cost = (i === currentDirection ? 0 : 1);
// Check if moving to this cell is optimal or not
if (dist[nr][nc] > dist[r] + cost) {
dist[nr][nc] = dist[r] + cost;
// If the adjacent cell is in the
// same direction as the previous one,
// then push the cell to the front
if (cost === 0) {
dq.unshift([nr, nc, i]);
}
else {
// If the adjacent cell is not
// in the same direction as the previous
// one, then push the cell to the back
dq.push([nr, nc, i]);
}
}
}
}
}
return dist[N - 1][N - 1];
} // Method to find the minimum number of turns function minimumTurns(N, maze) {
let directions = [
[0, 1], [1, 0], [0, -1], [-1, 0]
]; // Vector to move to an adjacent cell
// Explore all the four directions as initial direction
let res = Math.min(
solve(maze, 0, directions, N),
solve(maze, 1, directions, N),
solve(maze, 2, directions, N),
solve(maze, 3, directions, N)
);
return res === 1e9 ? -1 : res;
} // Input let N = 3; let maze = [ [1, 0, 1],
[1, 1, 0],
[0, 1, 1]
]; console.log(minimumTurns(N, maze)); |
3
Time Complexity: O(4 * N * N), where N is the number of rows or columns in the grid.
Auxiliary Space: O(N * N)