Open In App

Check if destination of given Matrix is reachable with required values of cells

Last Updated : 24 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a matrix mat[][] of size N*M and the destination (x, y) to be reached from (0, 0), the task is to find if you can reach the destination following the given criteria:

  • If the cell value is 0 you cannot move to that cell.
  • If the cell value is 1, you can move to the cell and do not need to have any special value.
  • In all other cases, you need to collect that value first before moving to that cell.

Movements in all four directions (up, down, left and right) are allowed and the positions where a specific value is situated are provided in a map name keys.  
 

Input: mat = {{1, 0, 0, 0}, {1, 1, 1, 1}, {0, 2, 0, 0}, {1, 1, 1, 1}}
keys: {(1, 3): 2, (2, 1): 3}, x = 3, y = 1
Output: True 
Explanation: In the above grid start from (0, 0) and 
fetch the value 2 from (1, 3). Now move to (2, 1) and reach the destination (3, 1).

Input: mat = {{1, 0, 0, 0}, {1, 1, 1, 1}, {0, 2, 0, 0}, {1, 1, 2, 1}}
keys: {(1, 3)=> 2, (2, 1)=> 3}, x = 3, y = 3
Output: True

 

Approach: The way to solve the problem is based on the concept of BFS:

We need to collect the values of the special cells with values greater than 1, thus Breadth-first traversal can be used to explore the closest levels first and move in all directions to collect the values and find path to reach the destination.

Follow the steps mentioned below to implement the idea:

  • Perform Breadth-first traversal in grid starting from (0, 0). Three cases can arise: 
    • Case 1 (When a cell has a value of 1): In this case, we simply push this coordinate in the queue for exploring.
    • Case 2 (When a cell needs a special value that is already collected): The cells that require the value can now be pushed into the queue for processing.
    • Case 3 (When a cell needs a special value that is not yet collected). In this case, push this cell into a map that represents the cells that cannot be traversed in the absence of a value. When the value is found while traversing the grid, then visit all the rooms that are stored in the map which require this value.
  • If the target room (x, y) is reached then return true otherwise false.

Below is the complete implementation of the above idea:

C++




// C++ code to implement the approach
  
#include <bits/stdc++.h>
using namespace std;
  
// Function to find if
// the destination can be reached or not
string Solvable(vector<vector<int> >& mat,
                map<pair<int, int>, int> Given_keys,
                int xDestination, int yDestination)
{
    // Contains the keys which were found while
    // traversing the grid.
    set<int> ListOfAvailableKeys;
    ListOfAvailableKeys.insert(1);
    queue<vector<int> > q;
    q.push({ 0, 0 });
  
    vector<vector<int> > dirr{
        { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 }
    };
  
    // Contains value -> ListOfCells which
    // require this value.
    unordered_map<int, vector<pair<int, int> > >
        Unopened_Rooms;
  
    while (!q.empty()) {
        vector<int> curr = q.front();
        q.pop();
  
        // Checking if at the destination
        if (curr[0] == xDestination
            && curr[1] == yDestination) {
            return "True";
        }
  
        // Case 2: If the current co-ordinate
        // contains any value.
        if (Given_keys.find({ curr[0], curr[1] })
            != Given_keys.end()) {
            int curr_key = Given_keys[{ curr[0], curr[1] }];
  
            // Insert the found value in
            // list of available values
            ListOfAvailableKeys.insert(curr_key);
  
            // Fetch the list of cells which require
            // the current value and then
            // push them in queue for exploration
            for (int i = 0;
                 i < Unopened_Rooms[curr_key].size(); i++) {
                q.push(
                    { Unopened_Rooms[curr_key][i].first,
                      Unopened_Rooms[curr_key][i].second });
            }
        }
  
        for (int i = 0; i < dirr.size(); i++) {
            int x = curr[0] + dirr[i][0];
            int y = curr[1] + dirr[i][1];
  
            if (x < 0 || y < 0 || x >= mat.size()
                || y >= mat[0].size() || mat[x][y] == 0) {
                continue;
            }
  
            // Case 3: if the cell requires a value
            // that currently we don't have.
            if (ListOfAvailableKeys.find(mat[x][y])
                == ListOfAvailableKeys.end()) {
                Unopened_Rooms[(mat[x][y])].push_back(
                    { x, y });
  
                // Mark the cell as visited.
                mat[x][y] = 0;
            }
  
            else {
                q.push({ x, y });
  
                // Mark that cell as visited.
                mat[x][y] = 0;
            }
        }
    }
    return "False";
}
  
// Driver Code
int main()
{
  
    vector<vector<int> > mat{ { 1, 0, 0, 0 },
                              { 1, 1, 1, 1 },
                              { 0, 2, 0, 0 },
                              { 1, 1, 2, 1 } };
    map<pair<int, int>, int> keys;
    keys[{ 1, 1 }] = 3;
    keys[{ 1, 3 }] = 2;
    int x = 3, y = 3;
  
    // Function Call
    cout << Solvable(mat, keys, x, y);
    return 0;
}


Python3




# Python3 code to implement the approach
  
# Function to find if
# the destination can be reached or not
def Solvable(mat, Given_keys, xDestination, yDestination):
  
    # Contains the keys which were found while
    # traversing the grid.
    ListOfAvailableKeys = set()
    ListOfAvailableKeys.add(1)
    q = []
    q.append([0, 0])
  
    dirr = [[1, 0], [0, 1], [-1, 0], [0, -1]]
  
    # Contains value -> ListOfCells which
    # require this value.
    Unopened_Rooms = {}
  
    while (len(q)):
        curr = q.pop(0)
  
        # Checking if at the destination
        if (curr[0] == xDestination and curr[1] == yDestination):
            return "True"
  
        # Case 2: If the current co-ordinate
        # contains any value.
        if ((curr[0], curr[1]) in Given_keys):
            curr_key = Given_keys[(curr[0], curr[1])]
  
            # Insert the found value in
            # list of available values
            ListOfAvailableKeys.add(curr_key)
  
            # Fetch the list of cells which require
            # the current value and then
            # push them in queue for exploration
            if curr_key in Unopened_Rooms:
                for i in range(len(Unopened_Rooms[curr_key])):
                    q.append(
                        (Unopened_Rooms[curr_key][i][0], Unopened_Rooms[curr_key][i][1]))
  
        for i in range(len(dirr)):
            x = curr[0] + dirr[i][0]
            y = curr[1] + dirr[i][1]
  
            if (x < 0 or y < 0 or x >= len(mat) or y >= len(mat[0]) or mat[x][y] == 0):
                continue
  
            # Case 3: if the cell requires a value
            # that currently we don't have.
            if (mat[x][y] not in ListOfAvailableKeys):
                if (mat[x][y] not in Unopened_Rooms):
                    Unopened_Rooms[(mat[x][y])] = []
                Unopened_Rooms[(mat[x][y])].append([x, y])
  
                # Mark the cell as visited.
                mat[x][y] = 0
  
            else:
                q.append([x, y])
  
                # Mark that cell as visited.
                mat[x][y] = 0
  
    return "False"
  
# Driver Code
mat = [[1, 0, 0, 0], [1, 1, 1, 1], [0, 2, 0, 0], [1, 1, 2, 1]]
keys = {}
keys[(1, 1)] = 3
keys[(1, 3)] = 2
x = 3
y = 3
  
# Function Call
print(Solvable(mat, keys, x, y))
  
# This code is contributed by phasing17


C#




// C# code to implement the approach
using System;
using System.Collections.Generic;
  
class GFG {
  
    // Function to find if
    // the destination can be reached or not
    static string Solvable(int[, ] mat,
                           Dictionary<string, int> Given_keys,
                           int xDestination, int yDestination)
    {
  
        // Contains the keys which were found while
        // traversing the grid.
        HashSet<int> ListOfAvailableKeys = new HashSet<int>();
        ListOfAvailableKeys.Add(1);
        List<int[]> q = new List<int[]>();
        q.Add(new[] { 0, 0 });
  
        int[, ] dirr = new int[, ] { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } };
  
        // Contains value -> ListOfCells which
        // require this value.
        Dictionary<int, List<int[]> > Unopened_Rooms = new Dictionary<int, List<int[]> >();
  
        while (q.Count > 0) {
            int[] curr = q[0];
            q.RemoveAt(0);
  
            // Checking if at the destination
            if (curr[0] == xDestination
                && curr[1] == yDestination) {
                return "True";
            }
  
            // Case 2: If the current co-ordinate
            // contains any value.
            string key = Convert.ToString(curr[0]) + "#" + Convert.ToString(curr[1]);
            if (Given_keys.ContainsKey(key)) {
                int curr_key = Given_keys[key];
  
                // Insert the found value in
                // list of available values
                ListOfAvailableKeys.Add(curr_key);
  
                // Fetch the list of cells which require
                // the current value and then
                // push them in queue for exploration
                if (Unopened_Rooms.ContainsKey(curr_key)) {
                    for (var i = 0;
                         i < Unopened_Rooms[curr_key].Count;
                         i++) {
                        q.Add(new[] {
                            Unopened_Rooms[curr_key][i][0],
                            Unopened_Rooms[curr_key][i][1] });
                    }
                }
            }
  
            for (int i = 0; i < dirr.GetLength(0); i++) {
                int x = curr[0] + dirr[i, 0];
                int y = curr[1] + dirr[i, 1];
  
                if (x < 0 || y < 0 || x >= mat.GetLength(0)
                    || y >= mat.GetLength(1) || mat[x, y] == 0) {
                    continue;
                }
  
                // Case 3: if the cell requires a value
                // that currently we don't have.
                if (!ListOfAvailableKeys.Contains(mat[x, y])) {
                    if (!Unopened_Rooms.ContainsKey(
                            mat[x, y]))
                        Unopened_Rooms[(mat[x, y])] = new List<int[]>();
                    Unopened_Rooms[(mat[x, y])].Add(new[] { x, y });
  
                    // Mark the cell as visited.
                    mat[x, y] = 0;
                }
  
                else {
                    q.Add(new[] { x, y });
  
                    // Mark that cell as visited.
                    mat[x, y] = 0;
                }
            }
        }
        return "False";
    }
  
    // Driver Code
    public static void Main(string[] args)
    {
        int[, ] mat = new[, ] { { 1, 0, 0, 0 }, { 1, 1, 1, 1 }, { 0, 2, 0, 0 }, { 1, 1, 2, 1 } };
        Dictionary<string, int> keys = new Dictionary<string, int>();
        keys["1#1"] = 3;
        keys["1#3"] = 2;
        int x = 3;
        int y = 3;
  
        // Function Call
        Console.WriteLine(Solvable(mat, keys, x, y));
    }
}
  
// This code is contributed by phasing17


Javascript




// JavaScript code to implement the approach
  
// Function to find if
// the destination can be reached or not
function Solvable(mat, Given_keys, xDestination,
                   yDestination)
{
    // Contains the keys which were found while
    // traversing the grid.
    let ListOfAvailableKeys = new Set();
    ListOfAvailableKeys.add(1);
    let q = [];
    q.push([ 0, 0 ]);
  
    let dirr = [ [ 1, 0 ], [ 0, 1 ], [ -1, 0 ], [ 0, -1 ] ];
  
    // Contains value -> ListOfCells which
    // require this value.
    let Unopened_Rooms = {};
  
    while (q.length) {
        let curr = q.shift();
  
        // Checking if at the destination
        if (curr[0] == xDestination
            && curr[1] == yDestination) {
            return "True";
        }
  
        // Case 2: If the current co-ordinate
        // contains any value.
        if (Given_keys.hasOwnProperty(
                [ curr[0], curr[1] ])) {
            let curr_key
                = Given_keys [[curr [0], curr [1]]];
  
            // Insert the found value in
            // list of available values
            ListOfAvailableKeys.add(curr_key);
  
            // Fetch the list of cells which require
            // the current value and then
            // push them in queue for exploration
            if (Unopened_Rooms.hasOwnProperty(curr_key)) {
                for (var i = 0;
                     i < Unopened_Rooms[curr_key].length;
                     i++) {
                    q.push([
                        Unopened_Rooms[curr_key][i][0],
                        Unopened_Rooms[curr_key][i][1]
                    ]);
                }
            }
        }
  
        for (let i = 0; i < dirr.length; i++) {
            let x = curr[0] + dirr[i][0];
            let y = curr[1] + dirr[i][1];
  
            if (x < 0 || y < 0 || x >= mat.length
                || y >= mat[0].length || mat[x][y] == 0) {
                continue;
            }
  
            // Case 3: if the cell requires a value
            // that currently we don't have.
            if (!ListOfAvailableKeys.has(mat[x][y])) {
                if (!Unopened_Rooms.hasOwnProperty(
                        mat[x][y]))
                    Unopened_Rooms[(mat[x][y])] = [];
                Unopened_Rooms[(mat[x][y])].push([ x, y ]);
  
                // Mark the cell as visited.
                mat[x][y] = 0;
            }
  
            else {
                q.push([ x, y ]);
  
                // Mark that cell as visited.
                mat[x][y] = 0;
            }
        }
    }
    return "False";
}
  
// Driver Code
let mat = [
    [ 1, 0, 0, 0 ], [ 1, 1, 1, 1 ], [ 0, 2, 0, 0 ],
    [ 1, 1, 2, 1 ]
];
let keys = {};
keys[[ 1, 1 ]] = 3;
keys[[ 1, 3 ]] = 2;
let x = 3;
let y = 3;
  
// Function Call
console.log(Solvable(mat, keys, x, y));
  
// This code is contributed by phasing17


Java




import java.util.*;
  
// java code to implement the approach
// Function to find if
// the destination can be reached or not
  
public class Solvable {
    public static boolean
    isSolvable(int[][] mat,
               Map<List<Integer>, Integer> givenKeys,
               int xDestination, int yDestination)
    {
        Set<Integer> listOfAvailableKeys = new HashSet<>();
        listOfAvailableKeys.add(1);
        Queue<List<Integer> > q = new LinkedList<>();
        q.offer(Arrays.asList(0, 0));
        int[][] dirr
            = { { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 } };
  
        // Contains value -> ListOfCells which
        // require this value.
  
        Map<Integer, List<List<Integer> > > unopenedRooms
            = new HashMap<>();
        while (!q.isEmpty()) {
            List<Integer> curr = q.poll();
  
            // Checking if at the destination
  
            if (curr.get(0) == xDestination
                && curr.get(1) == yDestination) {
                return true;
            }
  
            // Case 2: If the current co-ordinate
            // contains any value.
  
            if (givenKeys.containsKey(curr)) {
                int currKey = givenKeys.get(curr);
  
                // Insert the found value in
                // list of available values
  
                listOfAvailableKeys.add(currKey);
  
                // Fetch the list of cells which require
                // the current value and then
                // push them in queue for exploration
  
                if (unopenedRooms.containsKey(currKey)) {
                    for (List<Integer> room :
                         unopenedRooms.get(currKey)) {
                        q.offer(room);
                    }
                }
            }
            for (int i = 0; i < dirr.length; i++) {
                int x = curr.get(0) + dirr[i][0];
                int y = curr.get(1) + dirr[i][1];
                if (x < 0 || y < 0 || x >= mat.length
                    || y >= mat[0].length
                    || mat[x][y] == 0) {
                    continue;
                }
  
                // Case 3: if the cell requires a value
                // that currently we don't have.
  
                if (!listOfAvailableKeys.contains(
                        mat[x][y])) {
                    if (!unopenedRooms.containsKey(
                            mat[x][y])) {
                        unopenedRooms.put(
                            mat[x][y], new ArrayList<>());
                    }
                    unopenedRooms.get(mat[x][y]).add(
                        Arrays.asList(x, y));
  
                    // Mark the cell as visited.
  
                    mat[x][y] = 0;
                }
                else {
                    q.offer(Arrays.asList(x, y));
  
                    // Mark that cell as visited.
  
                    mat[x][y] = 0;
                }
            }
        }
        return false;
    }
    // Driver code
  
    public static void main(String[] args)
    {
        int[][] mat = { { 1, 0, 0, 0 },
                        { 1, 1, 1, 1 },
                        { 0, 2, 0, 0 },
                        { 1, 1, 2, 1 } };
        Map<List<Integer>, Integer> keys = new HashMap<>();
        keys.put(Arrays.asList(1, 1), 3);
        keys.put(Arrays.asList(1, 3), 2);
        int x = 3;
        int y = 3;
  
        // Function call
  
        System.out.println(isSolvable(mat, keys, x, y));
    }
}
  
// This code is contributed by NarasingaNikhil


Output

True

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



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads