Given a 2-D array matrix[][] of size ROW * COL and an integer K, where each cell matrix[i][j] is either 0 (empty) or 1 (obstacle). A pointer can move up, down, left, or right from and to an empty cell in a single step. The task is to find the minimum number of steps required to go from the source (0, 0) to the destination (ROW-1, COL-1) with less than or equal to K obstacle eliminations. An obstacle elimination is defined as changing a cell’s value matrix[i][j] from 1 to 0. If no path is possible then return -1.Â
Examples:
Input: matrix[][] = { {0,0,1},
                {1,0,1},
                {0,1,0} },Â
ROW = 3, COL = 3, K = 2
Output: 4
Explanation:Â
Change the value of matrix[0][2] and matrix[1][2] to 0 and the path is 0,0 -> 0,1 -> 0,2 -> 1,2 -> 2,2.
Input: matrix[][] = { {0,1,0},
                {1,1,0},Â
               {0,0,0},
               {0,0,0} },Â
ROW = 4, COL = 3, K = 1
Output: 5
Approach: The shortest path can be searched using BFS on a Matrix. Initialize a counter[][] vector, this array will keep track of the number of remaining obstacles that can be eliminated for each visited cell. Run a Breadth-first search on each cell and while keeping track of the number of obstacles we can still eliminate. At each cell, first, check if it is the destination cell or not. Then, it is checked if the current cell is an obstacle then the count of eliminations available is decremented by 1. If the cell value in the counter array has a lower value than the current variable then it is updated. The length array is updated at every step. Follow the steps below to solve the problem:
- Define 2 arrays dir_Row[4] and dir_Col[4] to store the direction coordinates possible from each point.
- Define a structure pointLoc as x, y, and k.
- Initialize a queue q[] of pointLoc datatype.
- Initialize a 2-D vector distance[ROW][COL] with values 0 to store the distance of each cell from the source cell.
- Initialize a 2-D vector obstackles[ROW][COL] with values -1 to store the count of available obstacle eliminations.
- Enqueue the value {0, 0, K} into the queue q[].
- Traverse in a while loop till the size of the queue q[] is greater than 0 and perform the following tasks:
- Initialize a variable te as the front of the queue q[].
- Initialize the variables x, y and tk as te.x, te.y and te.k.
- If the current cell equals the destination cell, then return the value of distance[x][y] as the answer.
- Dequeue the front element from the queue q[].
- If the current cell is an obstacle then if tk is greater than 0 then decrease its value by 1 else continue.
- If obstacles[x][y] is greater than equal to tk then continue else set its value as tk.
- Iterate over the range [0, 4) using the variable i and perform the following tasks:
- See all the neighboring cells (ax, ay) and check if they are valid cells or not. If not, then continue. Else enqueue {ax, ay, tk} into the queue q[] and set the value of distance[ax][ay] as distance[x][y] + 1.
- After performing the above steps, print the value -1 if no answer is found.
Below is the implementation of the above approach.
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; Â
#define ROW 3 #define COL 3 Â
// Direction Vectors int dir_Row[4] = { -1, 0, 1, 0 }; int dir_Col[4] = { 0, 1, 0, -1 }; Â
// Structure for storing coordinates // count of remaining obstacle eliminations struct pointLoc { Â Â Â Â int x, y, k; }; Â
// Function to perform BFS int BFS( int matrix[][COL], int k, pair< int , int > source, Â Â Â Â Â Â Â Â pair< int , int > destination) { Â
    // Stores pointLoc of each cell     queue< struct pointLoc> q; Â
    // Vector array to store distance of     // each cell from source cell     vector<vector< int > > distance(       ROW, vector< int >(COL, 0)); Â
    // Vector array to store count of     // available obstacle eliminations     vector<vector< int > > obstacles(       ROW, vector< int >(COL, -1)); Â
    // Push the source cell into queue     // and use as starting point     q.push({ source.first, source.second, k }); Â
    // Iterate while queue is not empty     while (!q.empty()) { Â
        struct pointLoc te = q.front();         int x = te.x;         int y = te.y;         int tk = te.k; Â
        // If current cell is same as         // destination then return distance         if (x == destination.first             && y == destination.second)             return distance[x][y]; Â
        q.pop(); Â
        // If current cell is an obstacle         // then decrement current value         // if possible else skip the cell         if (matrix[x][y] == 1) { Â
            if (tk > 0)                 tk--; Â
            else                 continue ;         } Â
        // Cell is skipped only if current         // value is less than previous         // value of cell         if (obstacles[x][y] >= tk)             continue ; Â
        // Else update value         obstacles[x][y] = tk; Â
        // Push all valid adjacent         // cells into queue         for ( int i = 0; i < 4; i++) { Â
            int ax = x + dir_Row[i];             int ay = y + dir_Col[i]; Â
            if (ax < 0 || ay < 0                 || ax >= ROW || ay >= COL)                 continue ; Â
            q.push({ ax, ay, tk }); Â
            // Update distance of current             // cell from source cell             distance[ax][ay] = distance[x][y] + 1;         }     } Â
    // If not possible to reach     // destination from source     return -1; } Â
// Driver Code int main() { Â
    // Given input     int matrix[ROW][COL]         = { { 0, 0, 1 },            { 1, 0, 1 },            { 0, 1, 0 } }; Â
    int k = 2; Â
    pair< int , int > source = { 0, 0 }; Â
    pair< int , int > destination = { 2, 2 }; Â
    cout << BFS(matrix, k, source, destination); Â
    return 0; } |
Java
// Java program for the above approach import java.util.*; Â
class GFG { Â
    static final int ROW = 3 ;     static final int COL = 3 ; Â
    // Direction Vectors     static int dir_Row[] = { - 1 , 0 , 1 , 0 };     static int dir_Col[] = { 0 , 1 , 0 , - 1 }; Â
    // Structure for storing coordinates     // count of remaining obstacle eliminations     static class pointLoc {         int x, y, k; Â
        public pointLoc( int x, int y, int k) {             super ();             this .x = x;             this .y = y;             this .k = k;         }     }; Â
    static class pair {         int first, second; Â
        public pair( int first, int second) {             this .first = first;             this .second = second;         }     } Â
    // Function to perform BFS     static int BFS( int matrix[][], int k, pair source, pair destination) { Â
        // Stores pointLoc of each cell         Queue<pointLoc> q = new LinkedList<GFG.pointLoc>(); Â
        // Vector array to store distance of         // each cell from source cell Â
        int [][] distance = new int [ROW][COL]; Â
        // Vector array to store count of         // available obstacle eliminations Â
        int [][] obstacles = new int [ROW][COL]; Â
        // Push the source cell into queue         // and use as starting point         q.add( new pointLoc(source.first, source.second, k)); Â
        // Iterate while queue is not empty         while (!q.isEmpty()) { Â
            pointLoc te = q.peek();             int x = te.x;             int y = te.y;             int tk = te.k; Â
            // If current cell is same as             // destination then return distance             if (x == destination.first && y == destination.second)                 return distance[x][y]; Â
            q.remove(); Â
            // If current cell is an obstacle             // then decrement current value             // if possible else skip the cell             if (matrix[x][y] == 1 ) { Â
                if (tk > 0 )                     tk--; Â
                else                     continue ;             } Â
            // Cell is skipped only if current             // value is less than previous             // value of cell             if (obstacles[x][y] >= tk)                 continue ; Â
            // Else update value             obstacles[x][y] = tk; Â
            // Push all valid adjacent             // cells into queue             for ( int i = 0 ; i < 4 ; i++) { Â
                int ax = x + dir_Row[i];                 int ay = y + dir_Col[i]; Â
                if (ax < 0 || ay < 0 || ax >= ROW || ay >= COL)                     continue ; Â
                q.add( new pointLoc(ax, ay, tk)); Â
                // Update distance of current                 // cell from source cell                 distance[ax][ay] = distance[x][y] + 1 ;             }         } Â
        // If not possible to reach         // destination from source         return - 1 ;     } Â
    // Driver Code     public static void main(String[] args) { Â
        // Given input         int matrix[][] = { { 0 , 0 , 1 }, { 1 , 0 , 1 }, { 0 , 1 , 0 } };         int k = 2 ;         pair source = new pair( 0 , 0 );         pair destination = new pair( 2 , 2 );         System.out.print(BFS(matrix, k, source, destination));     } } Â
// This code is contributed by shikhasingrajput |
Python3
# Python Program to implement # the above approach ROW = 3 COL = 3 Â
# Direction Vectors dir_Row = [ - 1 , 0 , 1 , 0 ] dir_Col = [ 0 , 1 , 0 , - 1 ] Â
# Structure for storing coordinates # count of remaining obstacle eliminations class pointLoc:     def __init__( self ,x, y, k):         self .x = x         self .y = y         self .k = k Â
Â
# Function to perform BFS def BFS(matrix, k, source,destination): Â
    # Stores pointLoc of each cell     q = [] Â
    # Vector array to store distance of     # each cell from source cell     distance = [ 0 for i in range (ROW)] Â
    for i in range ( len (distance)):         distance[i] = [ 0 for i in range (COL)] Â
Â
    # Vector array to store count of     # available obstacle eliminations     obstacles = [ 0 for i in range (ROW)]     for i in range ( len (obstacles)):         obstacles[i] = [ - 1 for i in range (COL)] Â
    # Push the source cell into queue     # and use as starting point     q.append(pointLoc(source[ 0 ], source[ 1 ], k)) Â
    # Iterate while queue is not empty     while ( len (q) > 0 ): Â
        te = q[ 0 ]         x = te.x         y = te.y         tk = te.k Â
        # If current cell is same as         # destination then return distance         if (x = = destination[ 0 ] and y = = destination[ 1 ]):             return distance[x][y] Â
        q = q[ 1 :] Â
        # If current cell is an obstacle         # then decrement current value         # if possible else skip the cell         if (matrix[x][y] = = 1 ): Â
            if (tk > 0 ):                 tk - = 1             else :                 continue Â
        # Cell is skipped only if current         # value is less than previous         # value of cell         if (obstacles[x][y] > = tk):             continue Â
        # Else update value         obstacles[x][y] = tk Â
        # Push all valid adjacent         # cells into queue         for i in range ( 4 ): Â
            ax = x + dir_Row[i]             ay = y + dir_Col[i] Â
            if (ax < 0 or ay < 0 or ax > = ROW or ay > = COL):                 continue Â
            q.append(pointLoc(ax, ay, tk)) Â
            # Update distance of current             # cell from source cell             distance[ax][ay] = distance[x][y] + 1 Â
    # If not possible to reach     # destination from source     return - 1 Â
# Driver Code Â
# Given input matrix = [[ 0 , 0 , 1 ],[ 1 , 0 , 1 ],[ 0 , 1 , 0 ]] Â
k = 2 source = [ 0 , 0 ] destination = [ 2 , 2 ] print (BFS(matrix, k, source, destination)) Â
# This code is contributed by shinjanpatra |
C#
// C# program for the above approach using System; using System.Collections.Generic; Â
class GFG{ Â
static readonly int ROW = 3; static readonly int COL = 3; Â
// Direction Lists static int []dir_Row = { -1, 0, 1, 0 }; static int []dir_Col = { 0, 1, 0, -1 }; Â
// Structure for storing coordinates // count of remaining obstacle eliminations class pointLoc { Â Â Â Â public int x, y, k; Â Â Â Â Â Â Â Â Â public pointLoc( int x, int y, int k) Â Â Â Â { Â Â Â Â Â Â Â Â this .x = x; Â Â Â Â Â Â Â Â this .y = y; Â Â Â Â Â Â Â Â this .k = k; Â Â Â Â } }; Â
class pair { Â Â Â Â public int first, second; Â
    public pair( int first, int second)     {         this .first = first;         this .second = second;     } } Â
// Function to perform BFS static int BFS( int [,]matrix, int k, pair source,                pair destination) {          // Stores pointLoc of each cell     Queue<pointLoc> q = new Queue<GFG.pointLoc>(); Â
    // List array to store distance of     // each cell from source cell     int [,] distance = new int [ROW, COL]; Â
    // List array to store count of     // available obstacle eliminations     int [,] obstacles = new int [ROW, COL]; Â
    // Push the source cell into queue     // and use as starting point     q.Enqueue( new pointLoc(source.first,                            source.second, k)); Â
    // Iterate while queue is not empty     while (q.Count != 0)     {         pointLoc te = q.Peek();         int x = te.x;         int y = te.y;         int tk = te.k;                  // If current cell is same as         // destination then return distance         if (x == destination.first &&             y == destination.second)             return distance[x, y]; Â
        q.Dequeue(); Â
        // If current cell is an obstacle         // then decrement current value         // if possible else skip the cell         if (matrix[x, y] == 1)         {             if (tk > 0)                 tk--;             else                 continue ;         } Â
        // Cell is skipped only if current         // value is less than previous         // value of cell         if (obstacles[x, y] >= tk)             continue ; Â
        // Else update value         obstacles[x, y] = tk; Â
        // Push all valid adjacent         // cells into queue         for ( int i = 0; i < 4; i++)         {             int ax = x + dir_Row[i];             int ay = y + dir_Col[i]; Â
            if (ax < 0 || ay < 0 ||              ax >= ROW || ay >= COL)                 continue ; Â
            q.Enqueue( new pointLoc(ax, ay, tk)); Â
            // Update distance of current             // cell from source cell             distance[ax, ay] = distance[x, y] + 1;         }     } Â
    // If not possible to reach     // destination from source     return -1; } Â
// Driver Code public static void Main(String[] args) {          // Given input     int [,]matrix = { { 0, 0, 1 },                       { 1, 0, 1 },                       { 0, 1, 0 } };     int k = 2;     pair source = new pair(0, 0);     pair destination = new pair(2, 2);          Console.Write(BFS(matrix, k, source, destination)); } } Â
// This code is contributed by shikhasingrajput |
Javascript
<script> Â
       // JavaScript Program to implement        // the above approach        let ROW = 3        let COL = 3 Â
       // Direction Vectors        let dir_Row = [-1, 0, 1, 0];        let dir_Col = [0, 1, 0, -1]; Â
       // Structure for storing coordinates        // count of remaining obstacle eliminations        class pointLoc {            constructor(x, y, k) {                this .x = x;                this .y = y;                this .k = k;            } Â
       }; Â
       // Function to perform BFS        function BFS(matrix, k, source,            destination) { Â
           // Stores pointLoc of each cell            let q = []; Â
           // Vector array to store distance of            // each cell from source cell            let distance = new Array(ROW);            for (let i = 0; i < distance.length; i++) {                distance[i] = new Array(COL).fill(0);            } Â
Â
           // Vector array to store count of            // available obstacle eliminations            let obstacles = new Array(ROW);            for (let i = 0; i < obstacles.length; i++) {                obstacles[i] = new Array(COL).fill(-1);            }                        // Push the source cell into queue            // and use as starting point            q.push( new pointLoc(source[0], source[1], k)); Â
           // Iterate while queue is not empty            while (q.length > 0) { Â
               let te = q[0];                let x = te.x;                let y = te.y;                let tk = te.k; Â
               // If current cell is same as                // destination then return distance                if (x == destination[0]                    && y == destination[1])                    return distance[x][y]; Â
               q.shift(); Â
               // If current cell is an obstacle                // then decrement current value                // if possible else skip the cell                if (matrix[x][y] == 1) { Â
                   if (tk > 0)                        tk--; Â
                   else                        continue ;                } Â
               // Cell is skipped only if current                // value is less than previous                // value of cell                if (obstacles[x][y] >= tk)                    continue ; Â
               // Else update value                obstacles[x][y] = tk; Â
               // Push all valid adjacent                // cells into queue                for (let i = 0; i < 4; i++) { Â
                   let ax = x + dir_Row[i];                    let ay = y + dir_Col[i]; Â
                   if (ax < 0 || ay < 0                        || ax >= ROW || ay >= COL)                        continue ; Â
                   q.push( new pointLoc(ax, ay, tk)); Â
                   // Update distance of current                    // cell from source cell                    distance[ax][ay] = distance[x][y] + 1;                }            } Â
           // If not possible to reach            // destination from source            return -1;        } Â
       // Driver Code Â
       // Given input        let matrix            = [[0, 0, 1],            [1, 0, 1],            [0, 1, 0]]; Â
       let k = 2;        let source = [0, 0];        let destination = [2, 2];        document.write(BFS(matrix, k, source, destination)); Â
   // This code is contributed by Potta Lokesh    </script> |
4
Time Complexity: O(ROW*COL*K)
Auxiliary Space: O(ROW*COL*K)
Â
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!