最多有 K 个障碍物的矩阵中两点之间的最短路径
给定一个大小为ROW * COL的二维数组matrix[][]和一个整数K,其中每个单元matrix[i][j]为0(空)或1(障碍物) 。只需一步,指针就可以从空单元格向上、向下、向左或向右移动。任务是找到从源(0, 0)到目的地(ROW-1, COL-1)所需的最小步数,且障碍消除小于或等于K。障碍消除被定义为将单元格的值matrix[i][j]从1更改为0。如果没有路径是可能的,则返回-1 。
例子:
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
方法:可以在矩阵上使用 BFS 搜索最短路径。初始化一个counter[][]向量,该数组将跟踪每个访问过的单元格可以消除的剩余障碍物的数量。在每个单元格上运行广度优先搜索,同时跟踪我们仍然可以消除的障碍物数量。在每个单元格中,首先检查它是否是目标单元格。然后,检查当前单元格是否是障碍物,然后可用的消除计数减1 。如果计数器数组中的单元格值的值低于当前变量,则更新它。每一步都会更新长度数组。请按照以下步骤解决问题:
- 定义 2 个数组dir_Row[4]和dir_Col[4]来存储每个点可能的方向坐标。
- 将结构pointLoc定义为x、y和k。
- 初始化pointLoc数据类型的队列q[] 。
- 用值0初始化一个二维向量distance[ROW][COL]以存储每个像元与源像元的距离。
- 用值-1初始化二维向量obstackles[ROW][COL]以存储可用障碍消除的计数。
- 将值{0, 0, K}排入队列q[]。
- 在while循环中遍历直到队列q[]的大小大于0并执行以下任务:
- 将变量te初始化为队列q[] 的前面。
- 将变量x、y和tk初始化为te.x、te.y和te.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)