矩阵或网格中两个单元格之间的最短距离
给定一个 N*M 阶的矩阵。查找从源单元格到目标单元格的最短距离,仅遍历有限的单元格。您也只能向上、向下、向左和向右移动。如果找到输出距离,否则为-1。
s 代表'来源'
d 代表“目的地”
* 代表您可以旅行的单元格
0 代表你不能旅行的单元格
此问题适用于单一来源和目的地。
例子:
Input : {'0', '*', '0', 's'},
{'*', '0', '*', '*'},
{'0', '*', '*', '*'},
{'d', '*', '*', '*'}
Output : 6
Input : {'0', '*', '0', 's'},
{'*', '0', '*', '*'},
{'0', '*', '*', '*'},
{'d', '0', '0', '0'}
Output : -1
这个想法是对矩阵单元进行 BFS(广度优先搜索)。请注意,如果图未加权,我们总是可以使用 BFS 来找到最短路径。
- 将每个单元格存储为一个节点,其中包含它们的行、列值和与源单元格的距离。
- 使用源单元启动 BFS。
- 制作一个已访问的数组,其中除了“0”单元格之外的所有单元格都具有“假”值,这些单元格被分配了“真”值,因为它们不能被遍历。
- 在每次移动中不断更新与源值的距离。
- 到达目的地时返回距离,否则返回-1(源和目的地之间不存在路径)。
CPP
// C++ Code implementation for above problem
#include
using namespace std;
#define N 4
#define M 4
// QItem for current location and distance
// from source location
class QItem {
public:
int row;
int col;
int dist;
QItem(int x, int y, int w)
: row(x), col(y), dist(w)
{
}
};
int minDistance(char grid[N][M])
{
QItem source(0, 0, 0);
// To keep track of visited QItems. Marking
// blocked cells as visited.
bool visited[N][M];
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++)
{
if (grid[i][j] == '0')
visited[i][j] = true;
else
visited[i][j] = false;
// Finding source
if (grid[i][j] == 's')
{
source.row = i;
source.col = j;
}
}
}
// applying BFS on matrix cells starting from source
queue q;
q.push(source);
visited[source.row][source.col] = true;
while (!q.empty()) {
QItem p = q.front();
q.pop();
// Destination found;
if (grid[p.row][p.col] == 'd')
return p.dist;
// moving up
if (p.row - 1 >= 0 &&
visited[p.row - 1][p.col] == false) {
q.push(QItem(p.row - 1, p.col, p.dist + 1));
visited[p.row - 1][p.col] = true;
}
// moving down
if (p.row + 1 < N &&
visited[p.row + 1][p.col] == false) {
q.push(QItem(p.row + 1, p.col, p.dist + 1));
visited[p.row + 1][p.col] = true;
}
// moving left
if (p.col - 1 >= 0 &&
visited[p.row][p.col - 1] == false) {
q.push(QItem(p.row, p.col - 1, p.dist + 1));
visited[p.row][p.col - 1] = true;
}
// moving right
if (p.col + 1 < M &&
visited[p.row][p.col + 1] == false) {
q.push(QItem(p.row, p.col + 1, p.dist + 1));
visited[p.row][p.col + 1] = true;
}
}
return -1;
}
// Driver code
int main()
{
char grid[N][M] = { { '0', '*', '0', 's' },
{ '*', '0', '*', '*' },
{ '0', '*', '*', '*' },
{ 'd', '*', '*', '*' } };
cout << minDistance(grid);
return 0;
}
Java
/*package whatever //do not write package name here */
// Java Code implementation for above problem
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
// QItem for current location and distance
// from source location
class QItem {
int row;
int col;
int dist;
public QItem(int row, int col, int dist)
{
this.row = row;
this.col = col;
this.dist = dist;
}
}
public class Maze {
private static int minDistance(char[][] grid)
{
QItem source = new QItem(0, 0, 0);
// To keep track of visited QItems. Marking
// blocked cells as visited.
firstLoop:
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++)
{
// Finding source
if (grid[i][j] == 's') {
source.row = i;
source.col = j;
break firstLoop;
}
}
}
// applying BFS on matrix cells starting from source
Queue queue = new LinkedList<>();
queue.add(new QItem(source.row, source.col, 0));
boolean[][] visited
= new boolean[grid.length][grid[0].length];
visited[source.row][source.col] = true;
while (queue.isEmpty() == false) {
QItem p = queue.remove();
// Destination found;
if (grid[p.row][p.col] == 'd')
return p.dist;
// moving up
if (isValid(p.row - 1, p.col, grid, visited)) {
queue.add(new QItem(p.row - 1, p.col,
p.dist + 1));
visited[p.row - 1][p.col] = true;
}
// moving down
if (isValid(p.row + 1, p.col, grid, visited)) {
queue.add(new QItem(p.row + 1, p.col,
p.dist + 1));
visited[p.row + 1][p.col] = true;
}
// moving left
if (isValid(p.row, p.col - 1, grid, visited)) {
queue.add(new QItem(p.row, p.col - 1,
p.dist + 1));
visited[p.row][p.col - 1] = true;
}
// moving right
if (isValid(p.row, p.col + 1, grid,
visited)) {
queue.add(new QItem(p.row, p.col + 1,
p.dist + 1));
visited[p.row][p.col + 1] = true;
}
}
return -1;
}
// checking where it's valid or not
private static boolean isValid(int x, int y,
char[][] grid,
boolean[][] visited)
{
if (x >= 0 && y >= 0 && x < grid.length
&& y < grid[0].length && grid[x][y] != '0'
&& visited[x][y] == false) {
return true;
}
return false;
}
// Driver code
public static void main(String[] args)
{
char[][] grid = { { '0', '*', '0', 's' },
{ '*', '0', '*', '*' },
{ '0', '*', '*', '*' },
{ 'd', '*', '*', '*' } };
System.out.println(minDistance(grid));
}
}
// This code is contributed by abhikelge21.
Python3
# Python3 Code implementation for above problem
# QItem for current location and distance
# from source location
class QItem:
def __init__(self, row, col, dist):
self.row = row
self.col = col
self.dist = dist
def __repr__(self):
return f"QItem({self.row}, {self.col}, {self.dist})"
def minDistance(grid):
source = QItem(0, 0, 0)
# Finding the source to start from
for row in range(len(grid)):
for col in range(len(grid[row])):
if grid[row][col] == 's':
source.row = row
source.col = col
break
# To maintain location visit status
visited = [[False for _ in range(len(grid[0]))]
for _ in range(len(grid))]
# applying BFS on matrix cells starting from source
queue = []
queue.append(source)
visited[source.row][source.col] = True
while len(queue) != 0:
source = queue.pop(0)
# Destination found;
if (grid[source.row][source.col] == 'd'):
return source.dist
# moving up
if isValid(source.row - 1, source.col, grid, visited):
queue.append(QItem(source.row - 1, source.col, source.dist + 1))
visited[source.row - 1][source.col] = True
# moving down
if isValid(source.row + 1, source.col, grid, visited):
queue.append(QItem(source.row + 1, source.col, source.dist + 1))
visited[source.row + 1][source.col] = True
# moving left
if isValid(source.row, source.col - 1, grid, visited):
queue.append(QItem(source.row, source.col - 1, source.dist + 1))
visited[source.row][source.col - 1] = True
# moving right
if isValid(source.row, source.col + 1, grid, visited):
queue.append(QItem(source.row, source.col + 1, source.dist + 1))
visited[source.row][source.col + 1] = True
return -1
# checking where move is valid or not
def isValid(x, y, grid, visited):
if ((x >= 0 and y >= 0) and
(x < len(grid) and y < len(grid[0])) and
(grid[x][y] != '0') and (visited[x][y] == False)):
return True
return False
# Driver code
if __name__ == '__main__':
grid = [['0', '*', '0', 's'],
['*', '0', '*', '*'],
['0', '*', '*', '*'],
['d', '*', '*', '*']]
print(minDistance(grid))
# This code is contributed by sajalmittaldei.
Javascript
输出
6
输出:
6