Given a N X N matrix (M) filled with 1 , 0 , 2 , 3 . Find the minimum numbers of moves needed to move from source to destination (sink) . while traversing through blank cells only. You can traverse up, down, right and left.
A value of cell 1 means Source.
A value of cell 2 means Destination.
A value of cell 3 means Blank cell.
A value of cell 0 means Blank Wall.
Note : there is only single source and single destination.they may be more than one path from source to destination(sink).each move in matrix we consider as ‘1’
Examples:
Input : M[3][3] = {{ 0 , 3 , 2 },
{ 3 , 3 , 0 },
{ 1 , 3 , 0 }};
Output : 4
Input : M[4][4] = {{ 3 , 3 , 1 , 0 },
{ 3 , 0 , 3 , 3 },
{ 2 , 3 , 0 , 3 },
{ 0 , 3 , 3 , 3 }};
Output : 4
Asked in: Adobe Interview
.

The idea is to use a Level graph ( Breadth First Traversal ). Consider each cell as a node and each boundary between any two adjacent cells be an edge. so the total number of Node is N*N.
- Create an empty Graph having N*N node ( Vertex ).
- Push all nodes into a graph.
- Note down the source and sink vertices.
- Now Apply level graph concept ( that we achieve using BFS). In which we find the level of every node from the source vertex. After that, we return ‘Level[d]’ ( d is the destination ). (which is the minimum move from source to sink )
Below is the implementation of the above idea.
C++
#include<bits/stdc++.h>
using namespace std;
#define N 4
class Graph
{
int V ;
list < int > *adj;
public :
Graph( int V )
{
this ->V = V ;
adj = new list< int >[V];
}
void addEdge( int s , int d ) ;
int BFS ( int s , int d) ;
};
void Graph :: addEdge ( int s , int d )
{
adj[s].push_back(d);
adj[d].push_back(s);
}
int Graph :: BFS( int s, int d)
{
if (s == d)
return 0;
int *level = new int [V];
for ( int i = 0; i < V; i++)
level[i] = -1 ;
list< int > queue;
level[s] = 0 ;
queue.push_back(s);
list< int >::iterator i;
while (!queue.empty())
{
s = queue.front();
queue.pop_front();
for (i = adj[s].begin(); i != adj[s].end(); ++i)
{
if (level[*i] < 0 || level[*i] > level[s] + 1 )
{
level[*i] = level[s] + 1 ;
queue.push_back(*i);
}
}
}
return level[d] ;
}
bool isSafe( int i, int j, int M[][N])
{
if ((i < 0 || i >= N) ||
(j < 0 || j >= N ) || M[i][j] == 0)
return false ;
return true ;
}
int MinimumPath( int M[][N])
{
int s , d ;
int V = N*N+2;
Graph g(V);
int k = 1 ;
for ( int i =0 ; i < N ; i++)
{
for ( int j = 0 ; j < N; j++)
{
if (M[i][j] != 0)
{
if ( isSafe ( i , j+1 , M ) )
g.addEdge ( k , k+1 );
if ( isSafe ( i , j-1 , M ) )
g.addEdge ( k , k-1 );
if (j< N-1 && isSafe ( i+1 , j , M ) )
g.addEdge ( k , k+N );
if ( i > 0 && isSafe ( i-1 , j , M ) )
g.addEdge ( k , k-N );
}
if ( M[i][j] == 1 )
s = k ;
if (M[i][j] == 2)
d = k;
k++;
}
}
return g.BFS (s, d) ;
}
int main()
{
int M[N][N] = {{ 3 , 3 , 1 , 0 },
{ 3 , 0 , 3 , 3 },
{ 2 , 3 , 0 , 3 },
{ 0 , 3 , 3 , 3 }
};
cout << MinimumPath(M) << endl;
return 0;
}
|
Java
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Queue;
class Graph {
private int V;
private ArrayList<ArrayList<Integer> > adj;
Graph( int v)
{
V = v;
adj = new ArrayList<>();
for ( int i = 0 ; i < v; i++)
adj.add( new ArrayList<>());
}
public void AddEdge( int s, int d)
{
adj.get(s).add(d);
adj.get(d).add(s);
}
public int BFS( int s, int d)
{
if (s == d)
return 0 ;
int [] level = new int [V];
for ( int i = 0 ; i < V; i++)
level[i] = - 1 ;
Queue<Integer> queue = new ArrayDeque<>();
level[s] = 0 ;
queue.add(s);
while (queue.size() > 0 ) {
s = queue.remove();
for ( int i : adj.get(s)) {
if (level[i] < 0
|| level[i] > level[s] + 1 ) {
level[i] = level[s] + 1 ;
queue.add(i);
}
}
}
return level[d];
}
}
class GFG {
static int N = 4 ;
static boolean IsSafe( int i, int j, int [][] M)
{
if ((i < 0 || i >= N) || (j < 0 || j >= N)
|| M[i][j] == 0 )
return false ;
return true ;
}
static int MinimumPath( int [][] M)
{
int s = 0 , d = 0 ;
int V = N * N + 2 ;
Graph g = new Graph(V);
int k = 1 ;
for ( int i = 0 ; i < N; i++) {
for ( int j = 0 ; j < N; j++) {
if (M[i][j] != 0 ) {
if (IsSafe(i, j + 1 , M))
g.AddEdge(k, k + 1 );
if (IsSafe(i, j - 1 , M))
g.AddEdge(k, k - 1 );
if (j < N - 1 && IsSafe(i + 1 , j, M))
g.AddEdge(k, k + N);
if (i > 0 && IsSafe(i - 1 , j, M))
g.AddEdge(k, k - N);
}
if (M[i][j] == 1 )
s = k;
if (M[i][j] == 2 )
d = k;
k++;
}
}
return g.BFS(s, d);
}
public static void main(String[] args)
{
int [][] M = { { 3 , 3 , 1 , 0 },
{ 3 , 0 , 3 , 3 },
{ 2 , 3 , 0 , 3 },
{ 0 , 3 , 3 , 3 } };
int ans = MinimumPath(M);
System.out.println(ans);
}
}
|
Python3
class Graph:
def __init__( self , V):
self .V = V
self .adj = [[] for i in range (V)]
def addEdge ( self , s , d ):
self .adj[s].append(d)
self .adj[d].append(s)
def BFS( self , s, d):
if (s = = d):
return 0
level = [ - 1 ] * self .V
queue = []
level[s] = 0
queue.append(s)
while ( len (queue) ! = 0 ):
s = queue.pop()
i = 0
while i < len ( self .adj[s]):
if (level[ self .adj[s][i]] < 0 or
level[ self .adj[s][i]] > level[s] + 1 ):
level[ self .adj[s][i]] = level[s] + 1
queue.append( self .adj[s][i])
i + = 1
return level[d]
def isSafe(i, j, M):
global N
if ((i < 0 or i > = N) or
(j < 0 or j > = N ) or M[i][j] = = 0 ):
return False
return True
def MinimumPath(M):
global N
s , d = None , None
V = N * N + 2
g = Graph(V)
k = 1
for i in range (N):
for j in range (N):
if (M[i][j] ! = 0 ):
if (isSafe (i , j + 1 , M)):
g.addEdge (k , k + 1 )
if (isSafe (i , j - 1 , M)):
g.addEdge (k , k - 1 )
if (j < N - 1 and isSafe (i + 1 , j , M)):
g.addEdge (k , k + N)
if (i > 0 and isSafe (i - 1 , j , M)):
g.addEdge (k , k - N)
if (M[i][j] = = 1 ):
s = k
if (M[i][j] = = 2 ):
d = k
k + = 1
return g.BFS (s, d)
N = 4
M = [[ 3 , 3 , 1 , 0 ], [ 3 , 0 , 3 , 3 ],
[ 2 , 3 , 0 , 3 ], [ 0 , 3 , 3 , 3 ]]
print (MinimumPath(M))
|
C#
using System;
using System.Collections.Generic;
public class Graph {
private int V;
private List< int >[] adj;
public Graph( int v)
{
V = v;
adj = new List< int >[ v ];
for ( int i = 0; i < v; i++)
adj[i] = new List< int >();
}
public void AddEdge( int s, int d)
{
adj[s].Add(d);
adj[d].Add(s);
}
public int BFS( int s, int d)
{
if (s == d)
return 0;
int [] level = new int [V];
for ( int i = 0; i < V; i++)
level[i] = -1;
Queue< int > queue = new Queue< int >();
level[s] = 0;
queue.Enqueue(s);
while (queue.Count > 0) {
s = queue.Dequeue();
foreach ( int i in adj[s])
{
if (level[i] < 0
|| level[i] > level[s] + 1) {
level[i] = level[s] + 1;
queue.Enqueue(i);
}
}
}
return level[d];
}
}
public class GFG {
static readonly int N = 4;
static bool IsSafe( int i, int j, int [, ] M)
{
if ((i < 0 || i >= N) || (j < 0 || j >= N)
|| M[i, j] == 0)
return false ;
return true ;
}
static int MinimumPath( int [, ] M)
{
int s = 0, d = 0;
int V = N * N + 2;
Graph g = new Graph(V);
int k = 1;
for ( int i = 0; i < N; i++) {
for ( int j = 0; j < N; j++) {
if (M[i, j] != 0) {
if (IsSafe(i, j + 1, M))
g.AddEdge(k, k + 1);
if (IsSafe(i, j - 1, M))
g.AddEdge(k, k - 1);
if (j < N - 1 && IsSafe(i + 1, j, M))
g.AddEdge(k, k + N);
if (i > 0 && IsSafe(i - 1, j, M))
g.AddEdge(k, k - N);
}
if (M[i, j] == 1)
s = k;
if (M[i, j] == 2)
d = k;
k++;
}
}
return g.BFS(s, d);
}
static void Main( string [] args)
{
int [, ] M = { { 3, 3, 1, 0 },
{ 3, 0, 3, 3 },
{ 2, 3, 0, 3 },
{ 0, 3, 3, 3 } };
int ans = MinimumPath(M);
Console.WriteLine(ans);
}
}
|
Javascript
<script>
class Graph{
constructor(V){
this .V = V
this .adj = new Array(V).fill(0).map(()=>[])
}
addEdge (s , d){
this .adj[s].push(d)
this .adj[d].push(s)
}
BFS(s, d){
if (s == d)
return 0
let level = new Array( this .V).fill(-1);
let queue = []
level[s] = 0
queue.push(s)
while (queue.length != 0){
s = queue.shift()
let i = 0
while (i < this .adj[s].length){
if (level[ this .adj[s][i]] < 0 ||
level[ this .adj[s][i]] > level[s] + 1 ){
level[ this .adj[s][i]] = level[s] + 1
queue.push( this .adj[s][i])
}
i += 1
}
}
return level[d]
}
}
function isSafe(i, j, M){
if ((i < 0 || i >= N) ||
(j < 0 || j >= N ) || M[i][j] == 0)
return false
return true
}
function MinimumPath(M){
let s = null , d = null
let V = N * N + 2
let g = new Graph(V)
let k = 1
for (let i=0;i<N;i++){
for (let j=0;j<N;j++){
if (M[i][j] != 0){
if (isSafe (i , j + 1 , M))
g.addEdge (k , k + 1)
if (isSafe (i , j - 1 , M))
g.addEdge (k , k - 1)
if (j < N - 1 && isSafe (i + 1 , j , M))
g.addEdge (k , k + N)
if (i > 0 && isSafe (i - 1 , j , M))
g.addEdge (k , k - N)
}
if (M[i][j] == 1)
s = k
if (M[i][j] == 2)
d = k
k += 1
}
}
return g.BFS (s, d)
}
let N = 4
let M = [[3 , 3 , 1 , 0 ], [3 , 0 , 3 , 3 ],
[2 , 3 , 0 , 3 ], [0 , 3 , 3 , 3]]
document.write(MinimumPath(M))
</script>
|
Another Approach: (DFS Implementation of the problem)
The same can be implemented using DFS where the complete path from the source is compared to get the minimum moves to the destination.
Approach:
- Loop through every element in the input matrix and create a Graph from that matrix
- Create a graph with N*N vertices.
- Add the edge from the k vertex to k+1/ k-1 (if the edge is to the left or right element in the matrix) or k to k+N/ k-N(if the edge is to the top or bottom element in the matrix).
- Always check whether the element exists in the matrix and element != 0.
- if(element == 1) map the source if (element == 2) map the destination.
- Perform DFS to the graph formed, from source to destination.
- Base condition: if source==destination returns 0 as the number of minimum moves.
- Minimum moves will be the minimum(the result of DFS performed on the unvisited adjacent vertices).
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
#define N 4
#define MAX (INT_MAX - 1)
using namespace std;
class Graph {
private :
int V;
vector< int >* adj;
public :
Graph( int V)
: V{ V }
{
adj = new vector< int >[V];
}
~Graph()
{
delete [] adj;
}
void add_edges( int u, int v)
{
adj[u].push_back(v);
}
int DFS( int s, int d, unordered_set< int >& visited)
{
if (s == d)
return 0;
int res{ MAX };
visited.insert(s);
for ( int item : adj[s])
if (visited.find(item) ==
visited.end())
res = min(res, 1 + DFS(item, d, visited));
return res;
}
};
bool is_safe( int arr[][4], int i, int j)
{
if ((i < 0 || i >= N) || (j < 0 || j >= N)
|| arr[i][j] == 0)
return false ;
return true ;
}
int min_moves( int arr[][N])
{
int s{ -1 }, d{ -1 }, V{ N * N };
int k{ 0 };
Graph g{ V };
for ( int i = 0; i < N; i++)
{
for ( int j = 0; j < N; j++) {
if (arr[i][j] != 0) {
if (is_safe(arr, i, j + 1))
g.add_edges(k, k + 1);
if (is_safe(arr, i, j - 1))
g.add_edges(k, k - 1);
if (is_safe(arr, i + 1, j))
g.add_edges(k, k + N);
if (is_safe(arr, i - 1, j))
g.add_edges(k, k - N);
}
if (arr[i][j] == 1)
s = k;
else if (arr[i][j] == 2)
d = k;
k++;
}
}
unordered_set< int > visited;
return g.DFS(s, d, visited);
}
int32_t main()
{
int arr[][N] = { { 3, 3, 1, 0 },
{ 3, 0, 3, 3 },
{ 2, 3, 0, 3 },
{ 0, 3, 3, 3 } };
cout << min_moves(arr) << endl;
return 0;
}
|
Java
import java.util.*;
class Graph {
private ArrayList<Integer>[] adj;
public Graph( int v)
{
adj = new ArrayList[v];
for ( int i = 0 ; i < v; i++)
adj[i] = new ArrayList<Integer>();
}
public void Add_edges( int u, int v) { adj[u].add(v); }
public int DFS( int s, int d, HashSet<Integer> visited)
{
if (s == d)
return 0 ;
int res = Integer.MAX_VALUE - 1 ;
visited.add(s);
for ( int item : adj[s])
{
if (!visited.contains(item)) {
res = Math.min(res, 1 + DFS(item, d, visited));
}
}
return res;
}
}
public class GFG {
static int N = 4 ;
static boolean Is_safe( int [][] arr, int i, int j)
{
if ((i < 0 || i >= N) || (j < 0 || j >= N)
|| arr[i][j] == 0 )
return false ;
return true ;
}
static int Min_moves( int [][] arr)
{
int s = - 1 , d = - 1 , V = N * N;
int k = 0 ;
Graph g = new Graph(V);
for ( int i = 0 ; i < N; i++) {
for ( int j = 0 ; j < N; j++) {
if (arr[i][j] != 0 ) {
if (Is_safe(arr, i, j + 1 ))
g.Add_edges(k, k + 1 );
if (Is_safe(arr, i, j - 1 ))
g.Add_edges(k, k - 1 );
if (Is_safe(arr, i + 1 , j))
g.Add_edges(k, k + N);
if (Is_safe(arr, i - 1 , j))
g.Add_edges(k, k - N);
}
if (arr[i][j] == 1 )
s = k;
else if (arr[i][j] == 2 )
d = k;
k++;
}
}
HashSet<Integer> visited = new HashSet<Integer>();
return g.DFS(s, d, visited);
}
public static void main (String[] args) {
int [][] arr = { { 3 , 3 , 1 , 0 },
{ 3 , 0 , 3 , 3 },
{ 2 , 3 , 0 , 3 },
{ 0 , 3 , 3 , 3 } };
int ans = Min_moves(arr);
System.out.println(ans);
}
}
|
Python3
visited = {}
adj = [[] for i in range ( 16 )]
def add_edges(u, v):
global adj
adj[u].append(v)
def DFS(s, d):
global visited
if (s = = d):
return 0
res = 10 * * 9
visited[s] = 1
for item in adj[s]:
if (item not in visited):
res = min (res, 1 + DFS(item, d))
return res
def is_safe(arr, i, j):
if ((i < 0 or i > = 4 ) or
(j < 0 or j > = 4 ) or arr[i][j] = = 0 ):
return False
return True
def min_moves(arr):
s, d, V = - 1 , - 1 , 16
k = 0
for i in range ( 4 ):
for j in range ( 4 ):
if (arr[i][j] ! = 0 ):
if (is_safe(arr, i, j + 1 )):
add_edges(k, k + 1 )
if (is_safe(arr, i, j - 1 )):
add_edges(k, k - 1 )
if (is_safe(arr, i + 1 , j)):
add_edges(k, k + 4 )
if (is_safe(arr, i - 1 , j)):
add_edges(k, k - 4 )
if (arr[i][j] = = 1 ):
s = k
elif (arr[i][j] = = 2 ):
d = k
k + = 1
return DFS(s, d)
if __name__ = = '__main__' :
arr = [ [ 3 , 3 , 1 , 0 ],
[ 3 , 0 , 3 , 3 ],
[ 2 , 3 , 0 , 3 ],
[ 0 , 3 , 3 , 3 ] ]
print (min_moves(arr))
|
C#
using System;
using System.Collections.Generic;
public class Graph {
private List< int >[] adj;
public Graph( int v)
{
adj = new List< int >[ v ];
for ( int i = 0; i < v; i++)
adj[i] = new List< int >();
}
public void Add_edges( int u, int v) { adj[u].Add(v); }
public int DFS( int s, int d, HashSet< int > visited)
{
if (s == d)
return 0;
int res = Int32.MaxValue - 1;
visited.Add(s);
foreach ( int item in adj[s])
{
if (!visited.Contains(item)) {
res = Math.Min(res,
1 + DFS(item, d, visited));
}
}
return res;
}
}
public class GFG
{
static readonly int N = 4;
static bool Is_safe( int [, ] arr, int i, int j)
{
if ((i < 0 || i >= N) || (j < 0 || j >= N)
|| arr[i, j] == 0)
return false ;
return true ;
}
static int Min_moves( int [, ] arr)
{
int s = -1, d = -1, V = N * N;
int k = 0;
Graph g = new Graph(V);
for ( int i = 0; i < N; i++) {
for ( int j = 0; j < N; j++) {
if (arr[i, j] != 0) {
if (Is_safe(arr, i, j + 1))
g.Add_edges(k, k + 1);
if (Is_safe(arr, i, j - 1))
g.Add_edges(k, k - 1);
if (Is_safe(arr, i + 1, j))
g.Add_edges(k, k + N);
if (Is_safe(arr, i - 1, j))
g.Add_edges(k, k - N);
}
if (arr[i, j] == 1)
s = k;
else if (arr[i, j] == 2)
d = k;
k++;
}
}
HashSet< int > visited = new HashSet< int >();
return g.DFS(s, d, visited);
}
static void Main( string [] args)
{
int [, ] arr = { { 3, 3, 1, 0 },
{ 3, 0, 3, 3 },
{ 2, 3, 0, 3 },
{ 0, 3, 3, 3 } };
int ans = Min_moves(arr);
Console.WriteLine(ans);
}
}
|
Javascript
let N = 4;
let visited = {};
let adj = Array.from({length: 16}, () => []);
function add_edges(u, v) {
adj[u].push(v);
}
function DFS(s, d) {
if (s == d) {
return 0;
}
let res = 10**9;
visited[s] = 1;
for (let item of adj[s]) {
if (!(item in visited)) {
res = Math.min(res, 1 + DFS(item, d));
}
}
return res;
}
function is_safe(arr, i, j) {
if ((i < 0 || i >= 4) ||
(j < 0 || j >= 4) || arr[i][j] == 0) {
return false ;
}
return true ;
}
function min_moves(arr) {
let s = -1, d = -1, V = N * N;
let k = 0;
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
if (arr[i][j] != 0) {
if (is_safe(arr, i, j + 1)) {
add_edges(k, k + 1);
}
if (is_safe(arr, i, j - 1)) {
add_edges(k, k - 1);
}
if (is_safe(arr, i + 1, j)) {
add_edges(k, k + 4);
}
if (is_safe(arr, i - 1, j)) {
add_edges(k, k - 4);
}
}
if (arr[i][j] == 1) {
s = k;
} else if (arr[i][j] == 2) {
d = k;
}
k += 1;
}
}
return DFS(s, d);
}
let Arr = [ [ 3, 3, 1, 0 ],
[ 3, 0, 3, 3 ],
[ 2, 3, 0, 3 ],
[ 0, 3, 3, 3 ] ];
console.log(min_moves(Arr));
|
If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
02 Feb, 2023
Like Article
Save Article