蓝桥杯省赛必学 模板 BFS 第1216题走迷宫 C++ Java Python

目录

主要是BFS模板题

思路和解题方法

数据结构选择:

搜索过程:

输入输出处理:

代码细节

map1 和 vis 数组:

nxy 数组:

node 结构体:

queue q 队列:

bfs() 函数:

c++ 代码

Java 版本(仅供参考)

Python 版本(仅供参考)

大概的模板


主要是BFS模板题

3.走迷宫 - 蓝桥云课 (lanqiao.cn)icon-default.png?t=N7T8https://www.lanqiao.cn/problems/1216/learning/?problem_list_id=30&page=1

思路和解题方法

思路是利用广度优先搜索(BFS)算法来找到从起始点到目标点的最短路径。

  1. 数据结构选择

    • 使用二维数组 map1 表示地图,其中 map1[i][j] 存储了第 i 行第 j 列的格子信息,如障碍物或者可通行的空地。
    • 使用二维数组 vis 来标记地图上的每个位置是否已经访问过,以避免重复访问和陷入无限循环。
    • 使用结构体 node 表示搜索过程中的每个节点,包含了节点的位置和步数。
    • 使用队列 queue<node> q 存储待访问的节点,在搜索过程中按照先进先出的顺序访问节点。
  2. 搜索过程

    • 从起始点开始,将起始节点加入队列,并标记为已访问。
    • 循环执行以下步骤,直到队列为空或者找到目标点:
      • 从队列中取出一个节点,表示当前位置和步数。
      • 遍历当前节点的四个相邻节点,计算它们的位置和步数。
      • 对于每个相邻节点,检查是否在地图范围内、是否可达、是否已访问,如果满足条件,则将该节点加入队列,并标记为已访问。
      • 如果找到目标点,返回当前步数,表示找到了最短路径。
    • 如果队列为空且未找到目标点,返回 -1,表示无法到达目标点。
  3. 输入输出处理

    • 从标准输入读入地图的行数和列数,地图的信息,起始点和目标点的坐标。
    • 输出从起始点到目标点的最短路径的步数。

代码细节

  1. map1vis 数组:

    • map1 数组表示地图,其中的元素 map1[i][j] 存储了第 i 行第 j 列的格子信息。通常,0 可能表示障碍物,1 表示可通行的空地。
    • vis 数组用来标记地图上的每个位置是否已经访问过。在搜索过程中,如果一个位置被访问过,就不应该再次访问,以防止陷入无限循环。
  2. nxy 数组:

    • nxy 是一个二维数组,用来表示四个方向的移动。对于每个元素 (i, j)i 表示在 x 轴上的移动,j 表示在 y 轴上的移动。在这段代码中,(1, 0) 表示向右移动,(-1, 0) 表示向左移动,(0, 1) 表示向下移动,(0, -1) 表示向上移动。
  3. node 结构体:

    • node 结构体用来表示搜索过程中的每个节点。它包含了三个成员变量:x 表示节点的 x 坐标,y 表示节点的 y 坐标,step 表示从起始点到该节点的步数。
  4. queue<node> q 队列:

    • q 是一个队列,用来存储待访问的节点。在广度优先搜索中,通常使用队列来按照先进先出的顺序访问节点。
  5. 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;
}

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。

  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值