📜  最多有 K 个障碍物的矩阵中两点之间的最短路径

📅  最后修改于: 2022-05-13 01:57:00.979000             🧑  作者: Mango

最多有 K 个障碍物的矩阵中两点之间的最短路径

给定一个大小为ROW * COL的二维数组matrix[][]和一个整数K,其中每个单元matrix[i][j]0(空)1(障碍物) 。只需一步,指针就可以从空单元格向上、向下、向左或向右移动。任务是找到从源(0, 0)到目的地(ROW-1, COL-1)所需的最小步数,且障碍消除小于或等于K。障碍消除被定义为将单元格的值matrix[i][j]1更改为0。如果没有路径是可能的,则返回-1

例子:

方法:可以在矩阵上使用 BFS 搜索最短路径。初始化一个counter[][]向量,该数组将跟踪每个访问过的单元格可以消除的剩余障碍物的数量。在每个单元格上运行广度优先搜索,同时跟踪我们仍然可以消除的障碍物数量。在每个单元格中,首先检查它是否是目标单元格。然后,检查当前单元格是否是障碍物,然后可用的消除计数减1 。如果计数器数组中的单元格值的值低于当前变量,则更新它。每一步都会更新长度数组。请按照以下步骤解决问题:

  • 定义 2 个数组dir_Row[4]dir_Col[4]来存储每个点可能的方向坐标。
  • 将结构pointLoc定义为x、yk。
  • 初始化pointLoc数据类型的队列q[]
  • 用值0初始化一个二维向量distance[ROW][COL]以存储每个像元与源像元的距离。
  • 用值-1初始化二维向量obstackles[ROW][COL]以存储可用障碍消除的计数。
  • 将值{0, 0, K}排入队列q[]。
  • 在while循环中遍历直到队列q[]的大小大于0并执行以下任务:
    • 将变量te初始化为队列q[] 的前面。
    • 将变量x、ytk初始化为te.x、te.yte.k。
    • 如果当前单元格等于目标单元格,则返回distance[x][y]的值作为答案。
    • 从队列q[] 中取出前面的元素。
    • 如果当前单元格是障碍物,则如果tk大于0 ,则将其值减小1 ,否则继续。
    • 如果障碍物[x][y]大于等于tk ,则继续,否则将其值设置为tk。
    • 使用变量i遍历范围[0, 4)并执行以下任务:
      • 查看所有相邻单元格(ax、ay)并检查它们是否是有效单元格。如果没有,那么继续。否则将{ax, ay, tk}加入队列q[]并将distance[ax][ay]的值设置为distance[x][y] + 1。
  • 执行上述步骤后,如果没有找到答案,则打印值-1

下面是上述方法的实现。

C++
// C++ program for the above approach
#include 
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 source,
        pair destination)
{
 
    // Stores pointLoc of each cell
    queue q;
 
    // Vector array to store distance of
    // each cell from source cell
    vector > distance(
      ROW, vector(COL, 0));
 
    // Vector array to store count of
    // available obstacle eliminations
    vector > obstacles(
      ROW, vector(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 source = { 0, 0 };
 
    pair 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 q = new LinkedList();
 
        // 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 q = new Queue();
 
    // 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


输出
4

时间复杂度: O( ROW*COL *K)
辅助空间: O( ROW*COL *K)