Shortest path between two points in a Matrix with at most K obstacles


In this article, we will find the shortest path between two points in a matrix. The matrix contains two types of cells, empty cells and cells which have obstacles. We are given an integer K, which represents that we can remove at most K obstacles to reach our destination.

In the approach discussed in this article, we will do a breadth first search (BFS) on the matrix to find the shortest path. We will use a queue data structure, which will store a vector of integers. The vector will have 3 integers, the x coordinate, the y coordinate and the number of obstacles we can remove on that particular path. We will also use another matrix, which will store the current highest number of obstacles we can remove after reaching a certain cell in the original matrix.

Problem Statement

We are given a matrix of size N*M, and an integer K. The matrix consists of two types of cells, empty cell which is represented by 0, and obstacles represented by a 1. We need to find the shortest way from (0,0) to (N-1, M-1), given that we can only remove at most K number of obstacles.

In a single move, we can move up, down, left and right from our current cell.

We cannot leave the boundaries of the matrix.

Sample Examples

Input

arr = 
{
  {0,1}
  {1,1}
}
k=1

Output

-1

Explanation

We will go to either {0,1} or to {1,0} from our starting index. Going to any one of these locations, we need to remove an obstacle.

Now, we need to go to {1,1}, but to do that we need to remove the obstacle on that cell, which is not possible since we have already removed one of the obstacles.

So, the output will be –1.

Input

arr = 
{
  {0,1}
  {1,1} 
}
k=2

Output

2

Explanation

We will go to either {0,1} or to {1,0} from our starting index. Going to any one of these locations, we need to remove an obstacle.

Now, we need to go to {1,1}, but to do that we need to remove the obstacle on that cell, which becomes possible now as we can remove two obstacles.

So, the output will be 2.

Input

arr = 
{
  {0,1,0}
  {1,1,1}
}
k=2

Output

3

Explanation

The shortest path is as follows −

{0,0} -> {0,1} -> {0,2} -> {1,2}

And we only need to remove 2 obstacles in this path.

Hence, the answer is 3.

Approach

In this approach, we will do a breadth first search (BFS) on the matrix to find the shortest path. We will use a queue data structure, which will store a vector of integers. The vector will have 3 integers, the x coordinate, the y coordinate and the number of obstacles we can remove on that particular path. We will also use another matrix, which will store the current highest number of obstacles we can remove after reaching a certain cell in the original matrix. We will make a while loop which will iterate till the queue becomes empty. In every iteration, we will check if the four directions up, down, left and right and see if they are visited before or if the current K is greater than the K when they were visited in the past. And depending on the case, we will push them in the queue and move on. We will iterate till we find the ending cell, or the queue becomes emoty.

Algorithm

  • Step 1 − Initialize a queue data structure, which will store vector of integers.

  • Step 1.1 −Initialize a matrix of size N*M, mn_k.

  • Step 2 − Check if the starting and ending points have obstacles, if so remove those obstacles and update K accordingly.

  • Step 3 − Add a vector containing {0,0,K} to the queue.

  • Step 4 − Loop till the queue becomes empty:

  • Step 4.1 − Get the current size of the queue in a variable, sz.

  • Step 4.2 − Loop from 0 to sz-1.

  • Step 4.2.1 − Get the top element from the queue and pop the queue.

  • Step 4.2.2 − If the element is (N-1, M-1), return the result.

  • Step 4.2.3 − Else, check the four directions from the element, up, down, left, right. For each direction check if we have a valid cell, and if that cell is visited before. If the cell is not visited before, or it has been visited will less K, add it to the queue and update the matrix, mn_k.

  • Step 4.2.4 − Increase the result by 1.

  • Step 5 − If the queue becomes empty and we break out of the while loop, return −1.

Example

#include <bits/stdc++.h> 
using namespace std; 
int Shortest_Path(vector<vector<int>> &arr,int k){
   int dist = 0;
   int n = arr.size() , m=arr[0].size();
   if(arr[0][0]==1){k--;arr[0][0]=0;}
   if(arr[n-1][m-1]==1){k--;arr[n-1][m-1]=0;}
   vector<vector<int>> mn_k(n,vector<int>(m,-1));
   queue<vector<int>> que;
   que.push({0,0,k});
   while(!que.empty()){
      int sz = que.size();
      for(int i=0;i<sz;i++){
         vector<int> t  = que.front();que.pop();
         if(t[0]==(n-1) && t[1]==(m-1))return dist;
         if(t[0]>0){
            int ck = t[2];
            if(arr[t[0]-1][t[1]]==1)t[2]--;
            if(t[2]>=0 && mn_k[t[0]-1][t[1]]<t[2]){
               mn_k[t[0]-1][t[1]] = t[2];
               t[0]--;
               que.push(t);
               t[0]++;
            }
            t[2] = ck;
         }
         if(t[0]<(n-1)){
            int ck = t[2];
            if(arr[t[0]+1][t[1]]==1)t[2]--;
            if(t[2]>=0 && mn_k[t[0]+1][t[1]]<t[2]){
               mn_k[t[0]+1][t[1]] = t[2];
               t[0]++;
               que.push(t);
               t[0]--;
            }
            t[2] = ck;
         }
         if(t[1]>0){
            int ck = t[2];
            if(arr[t[0]][t[1]-1]==1)t[2]--;
            if(t[2]>=0 && mn_k[t[0]][t[1]-1]<t[2]){
               mn_k[t[0]][t[1]-1] = t[2];
               t[1]--;
               que.push(t);
               t[1]++;
            }
            t[2] = ck;
         }
         if(t[1]<(m-1)){
            int ck = t[2];
            if(arr[t[0]][t[1]+1]==1)t[2]--;
            if(t[2]>=0 && mn_k[t[0]][t[1]+1]<t[2]){
               mn_k[t[0]][t[1]+1] = t[2];
               t[1]++;
               que.push(t);
               t[1]--;
            }
            t[2] = ck;
         }
      }
      dist++;
   } 
   return -1;
} 
int main(){ 
   vector<vector<int>> arr = {
      {0,1,0},
      {1,1,1}
   };
   int k = 2;
   cout<<Shortest_Path(arr,k)<<endl; 
   return 0; 
}

Output

3

Time complexity − O(N*M*K), where N is the number of rows, M is the number of columns and K is the number of obstacles we can remove

Space complexity − O(N*M*K)

Updated on: 01-Nov-2023

73 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements