📌  相关文章
📜  矩阵或网格中两个单元格之间的最短距离

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

矩阵或网格中两个单元格之间的最短距离

给定一个 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 来找到最短路径。

  1. 将每个单元格存储为一个节点,其中包含它们的行、列值和与源单元格的距离。
  2. 使用源单元启动 BFS。
  3. 制作一个已访问的数组,其中除了“0”单元格之外的所有单元格都具有“假”值,这些单元格被分配了“真”值,因为它们不能被遍历。
  4. 在每次移动中不断更新与源值的距离。
  5. 到达目的地时返回距离,否则返回-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