解题思路
BFS求最短路径解题思路
1. 问题分析
- 二维网格中找最短路径
- 可以上下左右四个方向移动
- 有障碍物不能通过
- 需要判断是否能到达目标点
2. 解题步骤
-
数据结构
- 使用二维数组存储网格 - 使用队列进行BFS - 使用二维数组记录距离 - 定义四个方向的移动:dx[] = {-1,1,0,0}, dy[] = {0,0,-1,1}
-
BFS实现
- 从起点开始BFS - 每次取出队首位置,尝试四个方向 - 对每个可以移动到的新位置: * 检查是否越界 * 检查是否是障碍物 * 检查是否已访问 * 更新距离并加入队列
-
判断结果
- 如果到达终点,返回距离 - 如果队列空了还没到达,返回-1
3. 注意事项
-
坐标转换:
- 输入是从1开始的坐标
- 数组索引从0开始
- 需要进行转换
-
边界检查:
- 检查是否越界
- 检查是否是障碍物
- 检查是否已访问
-
优化:
- 可以用visited数组代替dist数组
- 可以在找到终点时立即返回
代码
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
struct Point {
int x, y, step;
Point(int _x, int _y, int _s) : x(_x), y(_y), step(_s) {}
};
class Solution {
public:
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
int shortestPath(vector<string>& grid, int xs, int ys, int xt, int yt) {
int n = grid.size(), m = grid[0].size();
vector<vector<bool>> visited(n, vector<bool>(m, false));
queue<Point> q;
q.push(Point(xs-1, ys-1, 0)); // 坐标转换
visited[xs-1][ys-1] = true;
while (!q.empty()) {
Point cur = q.front();
q.pop();
// 到达终点
if (cur.x == xt-1 && cur.y == yt-1) {
return cur.step;
}
// 尝试四个方向
for (int i = 0; i < 4; i++) {
int nx = cur.x + dx[i];
int ny = cur.y + dy[i];
// 检查新位置是否有效
if (nx >= 0 && nx < n && ny >= 0 && ny < m
&& !visited[nx][ny] && grid[nx][ny] == '.') {
visited[nx][ny] = true;
q.push(Point(nx, ny, cur.step + 1));
}
}
}
return -1; // 无法到达
}
};
int main() {
int n, m;
cin >> n >> m;
int xs, ys, xt, yt;
cin >> xs >> ys >> xt >> yt;
vector<string> grid(n);
for (int i = 0; i < n; i++) {
cin >> grid[i];
}
Solution sol;
cout << sol.shortestPath(grid, xs, ys, xt, yt) << endl;
return 0;
}
import java.util.*;
public class Main {
static int[] dx = {-1, 1, 0, 0};
static int[] dy = {0, 0, -1, 1};
static class Point {
int x, y, step;
Point(int x, int y, int step) {
this.x = x;
this.y = y;
this.step = step;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int xs = sc.nextInt() - 1; // 坐标转换
int ys = sc.nextInt() - 1;
int xt = sc.nextInt() - 1;
int yt = sc.nextInt() - 1;
char[][] grid = new char[n][m];
for (int i = 0; i < n; i++) {
grid[i] = sc.next().toCharArray();
}
// BFS
boolean[][] visited = new boolean[n][m];
Queue<Point> q = new LinkedList<>();
q.offer(new Point(xs, ys, 0));
visited[xs][ys] = true;
int result = -1;
while (!q.isEmpty()) {
Point cur = q.poll();
if (cur.x == xt && cur.y == yt) {
result = cur.step;
break;
}
for (int i = 0; i < 4; i++) {
int nx = cur.x + dx[i];
int ny = cur.y + dy[i];
if (nx >= 0 && nx < n && ny >= 0 && ny < m
&& !visited[nx][ny] && grid[nx][ny] == '.') {
visited[nx][ny] = true;
q.offer(new Point(nx, ny, cur.step + 1));
}
}
}
System.out.println(result);
}
}
from collections import deque
def shortest_path(grid, xs, ys, xt, yt):
n, m = len(grid), len(grid[0])
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
# 坐标转换
xs, ys = xs-1, ys-1
xt, yt = xt-1, yt-1
# BFS
visited = [[False] * m for _ in range(n)]
q = deque([(xs, ys, 0)]) # (x, y, steps)
visited[xs][ys] = True
while q:
x, y, steps = q.popleft()
if x == xt and y == yt:
return steps
for i in range(4):
nx, ny = x + dx[i], y + dy[i]
if (0 <= nx < n and 0 <= ny < m
and not visited[nx][ny] and grid[nx][ny] == '.'):
visited[nx][ny] = True
q.append((nx, ny, steps + 1))
return -1
# 读入数据
n, m = map(int, input().split())
xs, ys, xt, yt = map(int, input().split())
grid = [input() for _ in range(n)]
# 输出结果
print(shortest_path(grid, xs, ys, xt, yt))
算法及复杂度分析
- 算法:BFS求最短路径
- 时间复杂度:
- 每个格子最多访问一次
- 空间复杂度:
- 需要距离数组和队列