BFS

本文介绍了广度优先搜索(BFS)的基本概念、实现方式以及适用问题。通过一个经典的洛谷P1443马的遍历问题,展示了如何利用BFS求解最短路径问题。代码示例详细解释了BFS在解决棋盘上马的行走步数问题,给出了完整的C++代码实现,并输出了满足题目要求的矩阵结果。
摘要由CSDN通过智能技术生成

BFS(广度优先搜索)

定义

广度优先搜索:总是以“广度”为第一关键词,碰到“岔道口”时,总是依次访问该岔道口能直接到达的所有节点(与初始状态越接近就越先访问),再按照它们被访问的顺序访问他们能直接到达的所有节点,以此类推

实现

根据广度优先搜索的特点,它往往使用队列实现

适用问题

BFS一般适用于最短路问题,在解的分布较为稀疏时,使用DFS会较慢,此时也可以考虑使用BFS

BFS伪代码描述(模板)

memset(ans, -1, sizeof(ans))//将保存的状态数组初始化,以便于确认是否访问过
void bfs(){
    queue<int> q;//也可定义在全局变量中
    q.push(s);//s为初始状态,即将初始状态入队
    while(!q.empty()){//循环到队列为空
        state now = q.front();//取出队首并保存,state根据题目需要而定
        //此时可以根据需要访问队首
        q.pop;//队首出队
        for(枚举所有可扩展状态){//扩展,即可以“往下走”的状态
            if (合法){//合法是指:未访问过,未在队内,满足题目限制条件
                q.push(合法节点);//将其入队,并根据题目要求进行维护
            }
        }
    }
}

经典例题

洛谷P1443 马的遍历

题目描述

有一个 n × m n\times m n×m的棋盘( 1 < n , m ≤ 400 1<n,m\le 400 1<n,m400),在某个点上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步,马的走法与国际象棋或中国象棋走法相同

输入格式

一行四个数据,棋盘的大小和马的坐标

输出格式

一个n*m的矩阵,代表马到达某个点最少要走几步(左对齐,宽5格,不能到达则输出-1)

输入输出样例

输入

3 3 1 1

输出

0    3    2    
3    -1   1    
2    1    4    
思路解析

题干中“最少几步”,我们可以考虑使用BFS做题

源代码
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>

using namespace std;

const int maxn = 400;

struct coord{//用结构coord保存坐标值
    int x;
    int y;
};

queue<coord> q;

int ans[maxn][maxn];//保存答案
int walk[8][2] = {{2, 1}, {1, 2}, {-1, 2}, {-2, 1},
                 {-2, -1}, {-1, -2}, {1, -2}, {2, -1}};//用增量数组表示前进方向,便于枚举

int main() {
    int n, m, sx, sy;//棋盘大小和起始坐标
    memset(ans, -1, sizeof(ans));//初始化
    cin >> n >> m >> sx >> sy;
   	//BFS
    coord tmp = {sx, sy};//
    q.push(tmp);//使用变量tmp存放初始坐标,并将其入队
    ans[sx][sy] = 0;//初始化ans[sx][sy]
    while(!q.empty()){
        //u变量用于保存每一次的队首
        coord u = q.front();
        int ux = u.x, uy = u.y;
        q.pop();//队首出队
        for (int i = 0; i < 8; ++i) {
            int x = ux + walk[i][0];
            int y = uy + walk[i][1];
            int d = ans[ux][uy];
            if (x < 1 || x > n || y < 1 || y > m || ans[x][y] != -1)
                continue;//遍历原始量+增量,若不合法则continue
            ans[x][y] = d + 1;//上一个点多走一步就到了这一个点
            coord tmp = {x, y};
            q.push(tmp);//这一个点入队
        }
    }
    for (int i = 1; i <= n; ++i, puts("")) {
        for (int j = 1; j <= m; ++j) {
            printf("%-5d", ans[i][j]);//按要求输出结果
        }
    }
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值