Open In App

Shortest path by removing K walls

Given a 2D binary matrix of size N * M, where 0 represents an empty space while 1 represents a wall you cannot walk through. You are also given an integer K. You can walk up, down, left, or right. Given that you can remove up to K walls, return the minimum number of steps to walk from the top left corner (0, 0) to the bottom right corner (N-1, M-1). 

Note: If there is no way to walk from the top left corner to the bottom right corner, return -1.



Examples:

Input: N = 3, M = 3, K = 1
mat = {{0, 0, 0}, {0, 0, 1}, {0, 1, 0}}
Output: 4
Explanation: We can remove any one of the walls and reach the bottom in 4 moves.



The below image gives the paths through which we can go from the source to the destination.

Image showing most of the paths from the source to the destination

If we carefully observe the paths shown above then, we will see that in these paths we have one cell that contains 1 and since we have k=1 hence we can traverse this cell also, and hence it gives the minimum steps.

Input: N = 2, M = 2, K = 0
mat[] = {{0, 1}, {1, 0}}
Output: -1
Explanation: There’s no way of reaching the bottom corner without removing any walls.

Approach:

The idea is to use breadth first search to calculate the shortest path from source to destination.

Follow the steps below to solve the problem:

Below is the implementation of the above approach. 




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the minimum number of steps
int shortestPath(vector<vector<int> > mat, int k)
{
    int n = mat.size();
    int m = mat[0].size();
    if (n == 1 && m == 1 && (mat[0][0] == 0 || k >= 1))
        return 0;
 
    vector<vector<vector<bool> > > visited(
        n, vector<vector<bool> >(
               m, vector<bool>(k + 1, false)));
    int steps = 0;
 
    queue<vector<int> > q;
    q.push({ 0, 0, k });
    int ar1[4] = { 1, -1, 0, 0 };
    int ar2[4] = { 0, 0, -1, 1 };
 
    // Loop to run a BFS
    while (!q.empty()) {
        int size = q.size();
 
        steps++;
        while (size--) {
            auto curr = q.front();
            int i = curr[0], j = curr[1], w = curr[2];
            q.pop();
            visited[i][j][w] = true;
            for (int dir = 0; dir < 4; dir++) {
                int new_x = i + ar1[dir];
                int new_y = j + ar2[dir];
                int new_k = w;
                if (new_x >= 0 && new_x < n && new_y >= 0
                    && new_y < m) {
                    if (mat[new_x][new_y] == 0
                        && !visited[new_x][new_y][new_k]) {
                        if (new_x == n - 1
                            && new_y == m - 1)
                            return steps;
                        q.push({ new_x, new_y, new_k });
                        visited[new_x][new_y][new_k] = true;
                    }
                    else if (mat[new_x][new_y] == 1
                             && new_k >= 1
                             && !visited[new_x][new_y]
                                        [new_k - 1]) {
                        if (new_x == n - 1
                            && new_y == m - 1)
                            return steps;
                        q.push({ new_x, new_y, new_k - 1 });
                        visited[new_x][new_y][new_k - 1]
                            = true;
                    }
                }
            }
        }
    }
    return -1;
}
 
// Driver code
int main()
{
    vector<vector<int> > mat
        = { { 0, 0, 0 }, { 0, 0, 1 }, { 0, 1, 0 } };
    int K = 1;
 
    // Function call
    cout << shortestPath(mat, K);
    return 0;
}




// Java code to implement the approach
 
import java.io.*;
import java.util.*;
 
class GFG {
     
    // Function to find the minimum number of steps
public static int shortestPath(int[][] mat, int k)
{
    int n = mat.length;
    int m = mat[0].length;
    if (n == 1 && m == 1 && (mat[0][0] == 0 || k >= 1))
        return 0;
 
    boolean[][][] visited = new boolean [n][m][k+1];
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            for(int q=0;q<k+1;q++)
            {
                visited[i][j][q]=false;
            }
        }
    }
     
    int steps = 0;
 
    ArrayList<ArrayList<Integer> > q
            = new ArrayList<ArrayList<Integer> >();
     
    q.add(new ArrayList<Integer>(Arrays.asList(0, 0, k)));
    int[] ar1 = { 1, -1, 0, 0 };
    int[] ar2 = { 0, 0, -1, 1 };
 
    // Loop to run a BFS
    while (q.size()!=0) {
        int size = q.size();
 
        steps++;
        while (size>0) {
            ArrayList<Integer> curr = q.get(0);
            int i = curr.get(0), j = curr.get(1), w = curr.get(2);
            q.remove(0);
            visited[i][j][w] = true;
            for (int dir = 0; dir < 4; dir++) {
                int new_x = i + ar1[dir];
                int new_y = j + ar2[dir];
                int new_k = w;
                if (new_x >= 0 && new_x < n && new_y >= 0
                    && new_y < m) {
                    if (mat[new_x][new_y] == 0
                        && !visited[new_x][new_y][new_k]) {
                        if (new_x == n - 1
                            && new_y == m - 1)
                            return steps;
                        q.add(new ArrayList<Integer>(Arrays.asList(new_x,new_y,new_k)));
                        visited[new_x][new_y][new_k] = true;
                    }
                    else if (mat[new_x][new_y] == 1
                            && new_k >= 1
                            && !visited[new_x][new_y]
                                        [new_k - 1]) {
                        if (new_x == n - 1
                            && new_y == m - 1)
                            return steps;
                        q.add(new ArrayList<Integer>(Arrays.asList(new_x,new_y,new_k-1)));
                        visited[new_x][new_y][new_k - 1]
                            = true;
                    }
                }
            }
            size--;
        }
    }
    return -1;
}
 
    public static void main (String[] args) {
        int[][] mat
        = { { 0, 0, 0 }, { 0, 0, 1 }, { 0, 1, 0 } };
    int K = 1;
 
    // Function call
    System.out.println(shortestPath(mat, K));
    }
}
 
// This code is contributed by Aman Kumar




# Python3 code to implement the approach
 
# Function to find the minimum number of steps
def shortestPath(mat, k):
 
    n = len(mat)
    m = len(mat[0])
    if (n == 1 and m == 1 and (mat[0][0] == 0 or k >= 1)):
        return 0
 
    visited = [[[False for _ in range(k+1)]
                for _ in range(m)] for _ in range(n)]
    steps = 0
 
    q = []
    q.append([0, 0, k])
 
    ar1 = [1, -1, 0, 0]
    ar2 = [0, 0, -1, 1]
 
    # Loop to run a BFS
    while (len(q) != 0):
        size = len(q)
 
        steps += 1
        while (size):
            curr = q.pop(0)
            i = curr[0]
            j = curr[1]
            w = curr[2]
 
            visited[i][j][w] = True
            for dir in range(0, 4):
                new_x = i + ar1[dir]
                new_y = j + ar2[dir]
                new_k = w
                if (new_x >= 0 and new_x < n and new_y >= 0
                        and new_y < m):
                    if (mat[new_x][new_y] == 0
                            and (not visited[new_x][new_y][new_k])):
                        if (new_x == n - 1
                                and new_y == m - 1):
                            return steps
                        q.append([new_x, new_y, new_k])
                        visited[new_x][new_y][new_k] = True
 
                    elif (mat[new_x][new_y] == 1
                          and new_k >= 1
                          and (not visited[new_x][new_y]
                               [new_k - 1])):
                        if (new_x == n - 1
                                and new_y == m - 1):
                            return steps
                        q.append([new_x, new_y, new_k - 1])
                        visited[new_x][new_y][new_k - 1] = True
            size -= 1
    return -1
 
# Driver code
if __name__ == "__main__":
 
    mat = [[0, 0, 0], [0, 0, 1], [0, 1, 0]]
    K = 1
 
    # Function call
    print(shortestPath(mat, K))
 
    # This code is contributed by rakeshsahni




// C# Code to implement the approach
using System;
using System.Collections.Generic;
public class Program
{
   
  // Function to find the minimum number of steps
  public static int ShortestPath(int[, ] mat, int k)
  {
    int n = mat.GetLength(0);
    int m = mat.GetLength(1);
    if (n == 1 && m == 1 && (mat[0, 0] == 0 || k >= 1))
      return 0;
    bool[, , ] visited = new bool[n, m, k + 1];
    int steps = 0;
    Queue<int[]> q = new Queue<int[]>();
    q.Enqueue(new int[] { 0, 0, k });
    int[] ar1 = { 1, -1, 0, 0 };
    int[] ar2 = { 0, 0, -1, 1 };
    // Loop to run a BFS
    while (q.Count != 0) {
      int size = q.Count;
      steps++;
      while (size-- > 0) {
        int[] curr = q.Dequeue();
        int i = curr[0], j = curr[1], w = curr[2];
        visited[i, j, w] = true;
        for (int dir = 0; dir < 4; dir++) {
          int new_x = i + ar1[dir];
          int new_y = j + ar2[dir];
          int new_k = w;
          if (new_x >= 0 && new_x < n
              && new_y >= 0 && new_y < m) {
            if (mat[new_x, new_y] == 0
                && !visited[new_x, new_y,
                            new_k]) {
              if (new_x == n - 1
                  && new_y == m - 1)
                return steps;
              q.Enqueue(new int[] {
                new_x, new_y, new_k });
              visited[new_x, new_y, new_k]
                = true;
            }
            else if (mat[new_x, new_y] == 1
                     && new_k >= 1
                     && !visited[new_x, new_y,
                                 new_k - 1]) {
              if (new_x == n - 1
                  && new_y == m - 1)
                return steps;
              q.Enqueue(new int[] {
                new_x, new_y, new_k - 1 });
              visited[new_x, new_y, new_k - 1]
                = true;
            }
          }
        }
      }
    }
    return -1;
  }
   
  // Driver Code
  public static void Main()
  {
    int[, ] mat
      = { { 0, 0, 0 }, { 0, 0, 1 }, { 0, 1, 0 } };
    int K = 1;
     
    // Function call
    Console.WriteLine(ShortestPath(mat, K));
  }
}
 
// This code is contributed by ishankhandelwals.




// JavaScript code to implement the approach
function shotestPath(mat, k) {
    let n = mat.length;
    let m = mat[0].length;
    if (n == 1 && m == 1 && (mat[0][0] == 0 || k >= 1))
        return 0;
    let visited = Array(n).fill().map(() => Array(m).fill().map(() => Array(k + 1).fill(false)));
    let steps = 0;
    let q = [];
    q.push([0, 0, k]);
    let ar1 = [1, -1, 0, 0];
    let ar2 = [0, 0, -1, 1];
     
    // Loop to run a BFS
    while (q.length > 0) {
        let size = q.length;
        steps++;
        while (size-- > 0) {
            let curr = q.shift();
            let i = curr[0], j = curr[1], w = curr[2];
            visited[i][j][w] = true;
            for (let dir = 0; dir < 4; dir++) {
                let new_x = i + ar1[dir];
                let new_y = j + ar2[dir];
                let new_k = w;
                if (new_x >= 0 && new_x < n && new_y >= 0
                    && new_y < m) {
                    if (mat[new_x][new_y] == 0
                        && !visited[new_x][new_y][new_k]) {
                        if (new_x == n - 1
                            && new_y == m - 1)
                            return steps;
                        q.push([new_x, new_y, new_k]);
                        visited[new_x][new_y][new_k] = true;
                    }
                    else if (mat[new_x][new_y] == 1
                        && new_k >= 1
                        && !visited[new_x][new_y]
                        [new_k - 1]) {
                        if (new_x == n - 1
                            && new_y == m - 1)
                            return steps;
                        q.push([new_x, new_y, new_k - 1]);
                        visited[new_x][new_y][new_k - 1]
                            = true;
                    }
                }
            }
        }
    }
    return -1;
}
 
// Driver code
let mat = [[0, 0, 0], [0, 0, 1], [0, 1, 0]];
let K = 1;
 
// Function call
console.log(shortestPath(mat, K));
 
// This code is contributed by ishankhandelwals.

Output
4

Time Complexity: O(N*M*K), For every cell (M*N), in the worst case we have to put that cell into the queue K times.
Space Complexity: O(N*M*K), In the worst case store all of those steps/paths in the visited set.


Article Tags :