Open In App

Check if destination is reachable by moving at most K step each time

Improve
Improve
Like Article
Like
Save
Share
Report

Given a binary matrix grid[][] of size M*N where ‘0‘ represents a blocked cell and ‘1’ represents a normal cell and a source (sx, sy) and destination (dx, dy). The task is to check if the destination is reachable from the source by moving at most K units of distance in a single step.

Examples:

Input: M = 4, N = 4, grid[][] = [[1, 1, 1, 1], [1, 0, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], sx = 0, sy = 0, dx = 3, dy = 3, K = 3
Output: True
Explanation: In this test case, the distance from the source to the destination is 3, which is less than or equal to K. Therefore, the destination is reachable.

Input: M = 4, N = 4, grid[][] = [[1, 1, 1, 1], [1, 0, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], sx = 0, sy = 0, dx = 3, dy = 3, K = 2
Output: False
Explanation: In this test case, the distance from the source to the destination is 3, which is greater than K. Therefore, the destination is not reachable.

Approach: The above problem can be solved using the below idea:

Adding the source to the queue. Explore all the points that can be reached from the top point of the queue and add them to the queue along with the distance covered. Keep checking whether a point has been visited or not. If the destination point is reached return true, otherwise false.

Follow the below steps to implement the idea:

  • Initialize an empty queue to store the cells we need to explore, and a 2D array to store the distance from the source for each cell.
  • Add the source cell to the queue and set its distance to 0.
  • While there are cells in the queue to explore:
    • Get the next cell to explore from the queue.
    • If the cell is the destination, return true.
    • Otherwise, explore the cells that can be reached in one step from the current cell.
    • For each valid and unexplored cell:
      • Add the cell to the queue and update its distance from the source.
      • If the distance from the source is greater than K, stop exploring this cell.
  • If we have explored all the cells and have not found the destination, return false.

Below is the implementation of the above approach.

C++




#include<bits/stdc++.h>
using namespace std;
 
// Function to check whether point lies within
// the boundary
bool isValid(vector<vector<int>>& grid, int x, int y, int m, int n)
{
   
  // Check if the cell is within the grid
  // boundaries and not blocked
  return x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1;
}
 
 
// Function to check whether it is possible to
// reach destination from source.
int isDestinationReachable(vector<vector<int>>& grid, int sx, int sy, int dx, int dy, int k)
{
  int m = grid.size();
  int n = grid[0].size();
 
  // Create a queue to store the cells
  // we need to explore
  queue<pair<int,int>>Queue;;
 
  // Create a 2D array to store the distance
  // from the source for each cell
  vector<vector<int>> distances(m,vector<int>(n,-1));
 
  // Add the source cell to the queue and
  // set its distance to 0
  Queue.push({sx, sy});
  distances[sx][sy] = 0;
 
  // Directions to move in the grid
  int dxi[] = {1, 0, -1, 0, -1, 1};
  int dyj[] = {0, 1, 0, -1, -1, 1};
 
  // While there are cells in the queue to explore
  while (!Queue.empty()) {
    // Get the next cell to explore
    auto p = Queue.front();
    Queue.pop();
 
    int x=p.first;
    int y=p.second;
    // If we have reached the destination,
    // return true
    if (x == dx && y == dy) {
      return true;
    }
 
    // Otherwise, explore the cells that can be
    // reached in one step
    for (int i = 0; i < 4; i++) {
      int new_x = x + dxi[i];
      int new_y = y + dyj[i];
 
      // If the new cell is valid and has
      // not been explored yet
      if (isValid(grid, new_x, new_y, m, n) && distances[new_x][new_y] == -1) {
        // Add the new cell to the queue and
        // update its distance from the source
        Queue.push({new_x, new_y});
        distances[new_x][new_y] = distances[x][y] + 1;
 
        // If the distance from the source is
        // greater than k, stop exploring this cell
        if (distances[new_x][new_y] > k) {
          return false;
 
        }
      }
    }
  }
 
  // If we have explored all the cells and not
  // found the destination, return false
  return false;
}
 
// Driver code
int main()
{
  vector<vector<int>> grid = {{1, 0, 1, 1},{1, 0, 1, 1},{1, 1, 1, 1},{1, 1, 1, 1}};
 
  int sx = 0;
  int sy = 0;
  int dx = 3;
  int dy = 3;
  int k = 3;
 
  // Function call
  if(isDestinationReachable(grid, sx, sy, dx, dy, k))
    cout<<"True";
  else
    cout<<"False";
  return 0;
}
 
// This code is contributed by ratiagrawal.


Java




// Java code to implement the approach
 
import java.io.*;
import java.util.*;
 
class GFG {
 
    // Directions to move in the grid
    static int[] dxi = { 1, 0, -1, 0, -1, 1 };
    static int[] dyj = { 0, 1, 0, -1, -1, 1 };
 
    // Function to check whether point lies within the
    // boundary
    static boolean isValid(int[][] grid, int x, int y,
                           int m, int n)
    {
        // Check if the cell is within the grid boundaries
        // and not blocked
        return x >= 0 && x < m && y >= 0 && y < n
            && grid[x][y] == 1;
    }
 
    // Function to check whether it is possible to reach
    // destination from source.
    static boolean isDestinationReachable(int[][] grid,
                                          int sx, int sy,
                                          int dx, int dy,
                                          int k)
    {
        int m = grid.length;
        int n = grid[0].length;
        // Create a queue to store the cells we need to
        // explore
        Queue<int[]> Queue = new LinkedList<>();
 
        // Create a 2D array to store the distance from the
        // source for each cell
        int[][] distances = new int[m][n];
        for (int i = 0; i < m; i++) {
            Arrays.fill(distances[i], -1);
        }
 
        // Add the source cell to the queue and set its
        // distance to 0
        Queue.add(new int[] { sx, sy });
        distances[sx][sy] = 0;
 
        // While there are cells in the queue to explore
        while (!Queue.isEmpty()) {
            // Get the next cell to explore
            int[] p = Queue.remove();
            int x = p[0];
            int y = p[1];
 
            // If we have reached the destination, return
            // true
            if (x == dx && y == dy) {
                return true;
            }
 
            // Otherwise, explore the cells that can be
            // reached in one step
            for (int i = 0; i < 4; i++) {
                int new_x = x + dxi[i];
                int new_y = y + dyj[i];
 
                // If the new cell is valid and has not been
                // explored yet
                if (isValid(grid, new_x, new_y, m, n)
                    && distances[new_x][new_y] == -1) {
                    // Add the new cell to the queue and
                    // update its distance from the source
                    Queue.add(new int[] { new_x, new_y });
                    distances[new_x][new_y]
                        = distances[x][y] + 1;
 
                    // If the distance from the source is
                    // greater than k, stop exploring this
                    // cell
                    if (distances[new_x][new_y] > k) {
                        return false;
                    }
                }
            }
        }
 
        // If we have explored all the cells and not found
        // the destination, return false
        return false;
    }
 
    public static void main(String[] args)
    {
        int[][] grid = { { 1, 0, 1, 1 },
                         { 1, 0, 1, 1 },
                         { 1, 1, 1, 1 },
                         { 1, 1, 1, 1 } };
        int sx = 0;
        int sy = 0;
        int dx = 3;
        int dy = 3;
        int k = 3;
 
        // Function call
        if (isDestinationReachable(grid, sx, sy, dx, dy,
                                   k)) {
            System.out.println("True");
        }
        else {
            System.out.println("False");
        }
    }
}
 
// This code is contributed by karthik.


Python3




# Python code to implement the approach
 
 
# Function to check whether it is possible to
# reach destination from source.
def isDestinationReachable(grid, sx, sy, dx, dy, k):
    m = len(grid)
    n = len(grid[0])
 
    # Create a queue to store the cells
    # we need to explore
    queue = []
 
    # Create a 2D array to store the distance
    # from the source for each cell
    distances = [[-1 for j in range(n)] for i in range(m)]
 
    # Add the source cell to the queue and
    # set its distance to 0
    queue.append((sx, sy))
    distances[sx][sy] = 0
 
    # Directions to move in the grid
    dx = [1, 0, -1, 0, -1, 1]
    dy = [0, 1, 0, -1, -1, 1]
 
    # While there are cells in the queue to explore
    while queue:
 
        # Get the next cell to explore
        x, y = queue.pop(0)
 
        # If we have reached the destination,
        # return true
        if x == dx and y == dy:
            return True
 
        # Otherwise, explore the cells that can be
        # reached in one step
        for i in range(4):
            new_x = x + dx[i]
            new_y = y + dy[i]
 
            # If the new cell is valid and has
            # not been explored yet
            if isValid(grid, new_x, new_y, m, n) \
                    and distances[new_x][new_y] == -1:
 
                # Add the new cell to the queue and
                # update its distance from the source
                queue.append((new_x, new_y))
                distances[new_x][new_y] = distances[x][y] + 1
 
                # If the distance from the source is
                # greater than k, stop exploring this cell
                if distances[new_x][new_y] > k:
                    break
 
    # If we have explored all the cells and not
    # found the destination, return false
    return False
 
 
# Function to check whether point lies within
# the boundary
def isValid(grid, x, y, m, n):
 
    # Check if the cell is within the grid
    # boundaries and not blocked
    return x >= 0 and x < m and y >= 0 and y < n and grid[x][y] == 1
 
 
# Driver code
if __name__ == '__main__':
 
    # Input
    grid = [[1, 0, 1, 1],
            [1, 0, 1, 1],
            [1, 1, 1, 1],
            [1, 1, 1, 1]
            ]
 
    sx = 0
    sy = 0
    dx = 3
    dy = 3
    K = 3
 
    # Function call
    print(isDestinationReachable(grid, sx, sy, dx, dy, K))


C#




using System;
using System.Collections.Generic;
 
public class GFG
{
   
  // Directions to move in the grid
  static int[] dxi = { 1, 0, -1, 0, -1, 1 };
  static int[] dyj = { 0, 1, 0, -1, -1, 1 };
 
  // Function to check whether point lies within the
  // boundary
  static bool IsValid(int[,] grid, int x, int y, int m, int n)
  {
    // Check if the cell is within the grid boundaries
    // and not blocked
    return x >= 0 && x < m && y >= 0 && y < n
      && grid[x, y] == 1;
  }
 
  // Function to check whether it is possible to reach
  // destination from source.
  static bool IsDestinationReachable(int[,] grid, int sx, int sy,
                                     int dx, int dy,
                                     int k)
  {
    int m = grid.GetLength(0);
    int n = grid.GetLength(1);
    // Create a queue to store the cells we need to
    // explore
    Queue<int[]> Queue = new Queue<int[]>();
 
    // Create a 2D array to store the distance from the
    // source for each cell
    int[,] distances = new int[m, n];
    for (int i = 0; i < m; i++)
    {
      for (int j = 0; j < n; j++)
      {
        distances[i, j] = -1;
      }
    }
 
    // Add the source cell to the queue and set its
    // distance to 0
    Queue.Enqueue(new int[] { sx, sy });
    distances[sx, sy] = 0;
 
    // While there are cells in the queue to explore
    while (Queue.Count > 0)
    {
      // Get the next cell to explore
      int[] p = Queue.Dequeue();
      int x = p[0];
      int y = p[1];
 
      // If we have reached the destination, return
      // true
      if (x == dx && y == dy)
      {
        return true;
      }
 
      // Otherwise, explore the cells that can be
      // reached in one step
      for (int i = 0; i < 4; i++)
      {
        int new_x = x + dxi[i];
        int new_y = y + dyj[i];
 
        // If the new cell is valid and has not been
        // explored yet
        if (IsValid(grid, new_x, new_y, m, n)
            && distances[new_x, new_y] == -1)
        {
          // Add the new cell to the queue and
          // update its distance from the source
          Queue.Enqueue(new int[] { new_x, new_y });
          distances[new_x, new_y]
            = distances[x, y] + 1;
 
          // If the distance from the source is
          // greater than k, stop exploring this
          // cell
          if (distances[new_x, new_y] > k)
          {
            return false;
          }
        }
      }
    }
 
    // If we have explored all the cells and not found
    // the destination, return false
    return false;
  }
 
  public static void Main (string[] args) {
    int[,] grid = new int[,] { { 1, 0, 1, 1 },
                              { 1, 0, 1, 1 },
                              { 1, 1, 1, 1 },
                              { 1, 1, 1, 1 } };
    int sx = 0;
    int sy = 0;
    int dx = 3;
    int dy = 3;
    int k = 3;
 
    // Function call
    if (IsDestinationReachable(grid, sx, sy, dx, dy,
                               k)) {
      Console.WriteLine("True");
    }
    else {
      Console.WriteLine("False");
    }
  }
}


Javascript




// Function to check whether it is possible to
// reach destination from source.
function isDestinationReachable(grid, sx, sy, dx, dy, k) {
  let m = grid.length;
  let n = grid[0].length;
 
  // Create a queue to store the cells
  // we need to explore
  let queue = [];
 
  // Create a 2D array to store the distance
  // from the source for each cell
  let distances = Array(m)
    .fill(0)
    .map(() => Array(n).fill(-1));
 
  // Add the source cell to the queue and
  // set its distance to 0
  queue.push([sx, sy]);
  distances[sx][sy] = 0;
 
  // Directions to move in the grid
  let dxi = [1, 0, -1, 0, -1, 1];
  let dyj = [0, 1, 0, -1, -1, 1];
 
  // While there are cells in the queue to explore
  while (queue.length) {
    // Get the next cell to explore
    let [x, y] = queue.shift();
 
    // If we have reached the destination,
    // return true
    if (x === dx && y === dy) {
      return true;
    }
 
    // Otherwise, explore the cells that can be
    // reached in one step
    for (let i = 0; i < 4; i++) {
      let new_x = x + dxi[i];
      let new_y = y + dyj[i];
 
      // If the new cell is valid and has
      // not been explored yet
      if (isValid(grid, new_x, new_y, m, n) && distances[new_x][new_y] == -1) {
        // Add the new cell to the queue and
        // update its distance from the source
        queue.push([new_x, new_y]);
        distances[new_x][new_y] = distances[x][y] + 1;
 
        // If the distance from the source is
        // greater than k, stop exploring this cell
        if (distances[new_x][new_y] > k) {
            return false;
         
        }
      }
    }
  }
 
  // If we have explored all the cells and not
  // found the destination, return false
  return false;
}
 
// Function to check whether point lies within
// the boundary
function isValid(grid, x, y, m, n) {
  // Check if the cell is within the grid
  // boundaries and not blocked
  return x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1;
}
 
// Driver code
let grid = [
  [1, 0, 1, 1],
  [1, 0, 1, 1],
  [1, 1, 1, 1],
  [1, 1, 1, 1],
];
 
let sx = 0;
let sy = 0;
let dx = 3;
let dy = 3;
let k = 3;
 
// Function call
console.log(isDestinationReachable(grid, sx, sy, dx, dy, k));
 
// This code is contributed by lokeshpotta20.


Output

False

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

Related Articles:



Last Updated : 10 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads