目录
主要是BFS模板题
3.走迷宫 - 蓝桥云课 (lanqiao.cn)https://www.lanqiao.cn/problems/1216/learning/?problem_list_id=30&page=1
思路和解题方法
思路是利用广度优先搜索(BFS)算法来找到从起始点到目标点的最短路径。
数据结构选择:
- 使用二维数组
map1
表示地图,其中map1[i][j]
存储了第i
行第j
列的格子信息,如障碍物或者可通行的空地。- 使用二维数组
vis
来标记地图上的每个位置是否已经访问过,以避免重复访问和陷入无限循环。- 使用结构体
node
表示搜索过程中的每个节点,包含了节点的位置和步数。- 使用队列
queue<node> q
存储待访问的节点,在搜索过程中按照先进先出的顺序访问节点。搜索过程:
- 从起始点开始,将起始节点加入队列,并标记为已访问。
- 循环执行以下步骤,直到队列为空或者找到目标点:
- 从队列中取出一个节点,表示当前位置和步数。
- 遍历当前节点的四个相邻节点,计算它们的位置和步数。
- 对于每个相邻节点,检查是否在地图范围内、是否可达、是否已访问,如果满足条件,则将该节点加入队列,并标记为已访问。
- 如果找到目标点,返回当前步数,表示找到了最短路径。
- 如果队列为空且未找到目标点,返回 -1,表示无法到达目标点。
输入输出处理:
- 从标准输入读入地图的行数和列数,地图的信息,起始点和目标点的坐标。
- 输出从起始点到目标点的最短路径的步数。
代码细节
map1
和vis
数组:
map1
数组表示地图,其中的元素map1[i][j]
存储了第i
行第j
列的格子信息。通常,0
可能表示障碍物,1
表示可通行的空地。vis
数组用来标记地图上的每个位置是否已经访问过。在搜索过程中,如果一个位置被访问过,就不应该再次访问,以防止陷入无限循环。
nxy
数组:
nxy
是一个二维数组,用来表示四个方向的移动。对于每个元素(i, j)
,i
表示在 x 轴上的移动,j
表示在 y 轴上的移动。在这段代码中,(1, 0)
表示向右移动,(-1, 0)
表示向左移动,(0, 1)
表示向下移动,(0, -1)
表示向上移动。
node
结构体:
node
结构体用来表示搜索过程中的每个节点。它包含了三个成员变量:x
表示节点的 x 坐标,y
表示节点的 y 坐标,step
表示从起始点到该节点的步数。
queue<node> q
队列:
q
是一个队列,用来存储待访问的节点。在广度优先搜索中,通常使用队列来按照先进先出的顺序访问节点。
bfs()
函数:
bfs()
函数实现了广度优先搜索算法。它从起始点开始,逐步探索地图上的可行路径,直到找到目标点或者搜索完所有可达的位置。- 在每一步中,它首先从队列中取出一个节点,然后根据当前节点的位置和步数,探索四个方向上的邻居节点。
- 如果邻居节点是可行的且未被访问过,则将该节点加入队列,并标记为已访问。
c++ 代码
#include<bits/stdc++.h> // 包含标准 C++ 库中的所有头文件,通常不建议在实际项目中使用,因为会增加编译时间和可能导致不可移植性
using namespace std;
int map1[110][110]; // 定义一个二维数组用来表示地图,其中map1[i][j]表示第i行第j列的地图信息
bool vis[110][110]; // 定义一个二维数组用来表示是否已经访问过某个位置
int ans; // 未被使用的变量
int x1; // 起始点的 x 坐标
int x2; // 目标点的 x 坐标
int y11; // 起始点的 y 坐标
int y2; // 目标点的 y 坐标
int nxy[4][2] = {1,0,-1,0,0,1,0,-1}; // 定义一个二维数组表示四个方向的移动,分别为向右、向左、向下、向上
int n, m; // 地图的行数和列数
struct node { // 定义一个结构体用来表示节点,包括节点的 x 坐标、y 坐标和步数
int x, y, step;
};
queue<node> q; // 定义一个队列,用来进行广度优先搜索
int bfs() { // 定义广度优先搜索函数
while (!q.empty()) { // 当队列不为空时循环执行
node temp = q.front(); // 取出队首元素
q.pop(); // 弹出队首元素
int x = temp.x; // 当前节点的 x 坐标
int y = temp.y; // 当前节点的 y 坐标
int step = temp.step; // 当前节点的步数
if (x == x2 && y == y2) { // 如果当前节点到达目标节点
return step; // 返回当前步数
}
for (int i = 0; i < 4; i++) { // 遍历四个方向
int nx = x + nxy[i][0]; // 计算新的 x 坐标
int ny = y + nxy[i][1]; // 计算新的 y 坐标
if (nx < 1 || nx > n || ny < 1 || ny > m || vis[nx][ny] || map1[nx][ny] == 0) { // 如果新的位置超出地图范围或者已经访问过或者是不可通过的位置
continue; // 跳过当前方向的搜索
}
vis[nx][ny] = 1; // 标记新的位置为已访问
q.push({nx, ny, step + 1}); // 将新的节点加入队列,并且步数加一
}
}
return -1; // 如果搜索完所有可达的位置都没有找到目标节点,则返回 -1
}
int main() {
cin >> n >> m; // 输入地图的行数和列数
for (int i = 1; i <= n; i++) { // 循环读入地图信息
for (int j = 1; j <= m; j++) {
cin >> map1[i][j]; // 读入地图的每一个格子的信息
}
}
cin >> x1 >> y11 >> x2 >> y2; // 输入起始点和目标点的坐标
node a;
a.x = x1, a.y = y11, a.step = 0; // 初始化起始节点信息
vis[x1][y11] = 1; // 标记起始节点为已访问
q.push(a); // 将起始节点加入队列
cout << bfs() << endl; // 输出广度优先搜索得到的结果,即最短路径的步数
return 0;
}
Java 版本(仅供参考)
import java.util.*;
class Main {
static int[][] map1; // 存储地图信息
static boolean[][] vis; // 记录访问过的位置
static int x1, x2, y11, y2; // 起始点和目标点的坐标
static int n, m; // 地图的行数和列数
static int[][] nxy = {{1,0},{-1,0},{0,1},{0,-1}}; // 四个方向的移动
static class Node { // 定义节点类
int x, y, step;
Node(int x, int y, int step) {
this.x = x;
this.y = y;
this.step = step;
}
}
// 广度优先搜索
public static int bfs() {
Queue<Node> q = new LinkedList<>(); // 使用队列保存待访问的节点
q.add(new Node(x1, y11, 0)); // 将起始节点加入队列
vis[x1][y11] = true; // 标记起始节点已访问
while (!q.isEmpty()) {
Node temp = q.poll(); // 取出队首节点
int x = temp.x;
int y = temp.y;
int step = temp.step;
if (x == x2 && y == y2) { // 如果到达目标点
return step; // 返回步数
}
for (int i = 0; i < 4; i++) { // 遍历四个方向
int nx = x + nxy[i][0];
int ny = y + nxy[i][1];
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && !vis[nx][ny] && map1[nx][ny] == 1) {
// 判断新位置是否合法、未访问过、可通行
vis[nx][ny] = true; // 标记为已访问
q.add(new Node(nx, ny, step + 1)); // 加入队列
}
}
}
return -1; // 没有找到目标点,返回 -1
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
map1 = new int[n + 1][m + 1]; // 初始化地图数组
vis = new boolean[n + 1][m + 1]; // 初始化访问数组
// 读入地图信息
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
map1[i][j] = scanner.nextInt();
}
}
// 读入起始点和目标点坐标
x1 = scanner.nextInt();
y11 = scanner.nextInt();
x2 = scanner.nextInt();
y2 = scanner.nextInt();
// 输出最短路径的步数
System.out.println(bfs());
}
}
Python 版本(仅供参考)
from collections import deque
nxy = [(1, 0), (-1, 0), (0, 1), (0, -1)] # 四个方向的移动
# 广度优先搜索
def bfs():
q = deque() # 使用双端队列保存待访问的节点
q.append((x1, y11, 0)) # 将起始节点加入队列
vis[x1][y11] = True # 标记起始节点已访问
while q:
x, y, step = q.popleft() # 取出队首节点
if x == x2 and y == y2: # 如果到达目标点
return step # 返回步数
for dx, dy in nxy: # 遍历四个方向
nx, ny = x + dx, y + dy
if 1 <= nx <= n and 1 <= ny <= m and not vis[nx][ny] and map1[nx][ny] == 1:
# 判断新位置是否合法、未访问过、可通行
vis[nx][ny] = True # 标记为已访问
q.append((nx, ny, step + 1)) # 加入队列
return -1 # 没有找到目标点,返回 -1
# 读入地图的行数和列数
n, m = map(int, input().split())
# 初始化地图和访问数组
map1 = [[0] * (m + 1) for _ in range(n + 1)]
vis = [[False] * (m + 1) for _ in range(n + 1)]
# 读入地图信息
for i in range(1, n + 1):
map1[i][1:] = map(int, input().split())
# 读入起始点和目标点的坐标
x1, y11, x2, y2 = map(int, input().split())
# 输出最短路径的步数
print(bfs())
大概的模板
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
struct Node {
int x, y;
// 其他节点信息
};
vector<vector<int>> map1; // 地图信息
vector<vector<bool>> vis; // 标记是否访问过
vector<vector<int>> nxy= {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; // 四个方向的移动
// BFS函数模板
void bfs() {
int n = map1.size();
int m = map1[0].size();
queue<Node> q;
// 加入起始节点
q.push({/* 起始节点的 x 坐标 */, /* 起始节点的 y 坐标 */});
vis[/* 起始节点的 x 坐标 */][/* 起始节点的 y 坐标 */] = true;
while (!q.empty()) {
Node cur = q.front();
q.pop();
// 处理当前节点信息
for (auto& dir : direction) {
int nx = nxy.x + dir[0];
int ny = nxy.y + dir[1];
if (nx >= 0 && nx < n && ny >= 0 && ny < m && !vis[nx][ny]) {
vis[nx][ny] = true;
q.push({nx, ny});
// 可以在这里添加其他需要处理的逻辑
}
}
}
}
int main() {
int n, m;
cin >> n >> m;
map1.resize(n, vector<int>(m));
vis.resize(n, vector<bool>(m, false));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cin >> map1[i][j];
}
}
// 填入起始节点的坐标
// int startX, startY;
// cin >> startX >> startY;
bfs();
return 0;
}
觉得有用的话可以点点赞,支持一下。
如果愿意的话关注一下。会对你有更多的帮助。
每天都会不定时更新哦 >人< 。