概念
广度优先搜索(BFS)是图和树的搜索算法,它一层层地遍历节点,像波纹一样由近及远地扩展。想象一下在湖面上扔了一块石头,波纹会从落石处开始向四周扩散。同理,BFS从一个起点开始,先访问所有的近邻节点,然后再逐步移动到更远的节点。
BFS通常使用队列来实现,队列先进先出的特性正好符合BFS逐层访问的需求。当我们从队列中取出一个节点时,我们将其所有未访问的近邻节点入队,这样就可以按顺序访问每一层的节点。
在实际应用中,BFS常用于找到两点间的最短路径,如在迷宫中找到出口或在社交网络中找到两人之间的联系路径。这种方法保证了我们总是尽可能快地到达目标。
1、悟空救师傅-4472
这个问题是一个典型的广度优先搜索(BFS)问题,在一个给定的 ( n \times n ) 矩阵上,需要找到从起点 (1,1) 到达终点(师傅的位置,标记为2)的最短路径。
输入描述:
- 第一行是一个整数 ( n ),表示矩阵的大小。
- 接下来是一个 ( n \times n ) 的矩阵,0 表示可以通过,1 表示无法通过,2 表示师傅的位置。
输出描述:
- 一个整数,表示悟空找到师傅的最少步数。如果无法找到师傅,则输出 -1。
样例输入输出解释:
样例输入1给出了一个 ( 5 \times 5 ) 的矩阵,悟空可以在 5 步内找到师傅。
样例输入2也是一个 ( 5 \times 5 ) 的矩阵,但在这个案例中,悟空无法到达师傅的位置,因此输出为 -1。
代码解析:
代码使用广度优先搜索(BFS)算法来找到从起点到终点的最短路径。定义了一个 node
结构体来存储每个节点的位置和步数,以及两个数组 mp
和 vis
分别用于存储矩阵和标记节点是否已被访问。
bfs
函数执行 BFS 搜索,使用队列 q
来存储待访问的节点。对每个节点,检查其四个方向(上、下、左、右)的相邻节点,如果相邻节点可达且未被访问,则将其加入队列,并更新步数。
在 main
函数中,首先读取矩阵大小 n
和矩阵本身。然后进行一些边界情况的检查,最后调用 bfs
函数来执行搜索。
性能考量:
由于矩阵的大小最多为 (50 \times 50),BFS 算法的时间复杂度是可接受的。对于这个问题的规模,该算法是有效的。
#include<bits/stdc++.h>
using namespace std;
struct node{
int x,y;
int step;
};
queue<node> q;
int mp[55][55], vis[55][55];
int g[4][2] = {
{
-1,0}, {
1,0}, {
0,-1}, {
0,1}};
int n;
void bfs() {
node t = {
1, 1, 0};
q.push(t);
vis[1][1] = 1;
while(!q.empty()) {
t = q.front();
q.pop();
if(mp[t.x][t.y] == 2) {
cout << t.step << endl;
return;
}
for(int i = 0; i < 4; i++) {
int nx = t.x + g[i][0];
int ny = t.y + g[i][1];
if(nx > 0 && nx <= n && ny > 0 && ny <= n && vis[nx][ny] == 0 && mp[nx][ny] != 1) {
vis[nx][ny] = 1;
node next = {
nx, ny, t.step + 1};
q.push(next);
}
}
}
cout << -1 << endl; // Add newline for clean output
}
int main() {
cin >> n;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
cin >> mp[i][j];
}
}
if(mp[1][1] == 1) {
cout << -1 << endl;
return 0;
} else if(mp[1][1] == 2) {
cout << 0 << endl;
return 0;
}
bfs();
return 0;
}
2、棋盘游戏-3259
这个问题是在一个 (n \times n) 棋盘上进行的,需要计算从 (1,1) 位置的棋子到达帅棋位置的最少步数。棋子每次移动有8个方向可供选择。
输入描述:
- 第一行是一个整数 (n),表示棋盘的规模。
- 下面是一个 (n \times n) 的矩阵,0 表示可以通过,1 表示无法通过,# 表示对方帅棋。
输出描述:
- 如果棋子能移动到对方帅棋,输出最少的步数;不能则输出 -1。
样例输入输出解释:
样例输入1和样例输入2分别给出了 (5 \times 5) 的棋盘的两个配置,输出是到达帅棋位置的最少步数。
代码解析:
代码使用广度优先搜索(BFS)算法来找到从起点到终点的最短路径。定义了一个 node
结构体来存储每个节点的位置和步数,以及两个数组 mp
和 vis
分别用于存储矩阵和标记节点是否已被访问。
bfs
函数执行 BFS 搜索,使用队列 q
来存储待访问的节点。对每个节点,检查其八个方向的相邻节点,如果相邻节点可达且未被访问,则将其加入队列,并更新步数。
在 main
函数中,首先读取矩阵大小 n
和矩阵本身。然后进行一些边界情况的检查,最后调用 bfs
函数来执行搜索。
性能考量:
由于矩阵的大小最多为 (50 \times 50),BFS 算法的时间复杂度是可接受的。对于这个问题的规模,该算法是有效的。
#include<bits/stdc++.h>
using namespace std;
char mp[101][101];
bool vis[101][101];
struct node{
int x,y,step;
}t,p;
queue<node>q;//结构体队列
int n,g[8][2]={
-1,0,-1,1,0,1,1,1,1,0,1,-1,0,-1,-1,-1};
void bfs(){
t.x=1,t.y=1,t.step=0;
q.push(t);
while(!q.empty()){
t=q.front();
q.pop();
if(mp[t.x][t.y]=='#'){
cout<<t.step;
return;
}
for(int i=0;i<8;i++){
int nx=t.x+g[i][0];
int ny=t.y+g[i][1];
if(nx<1||nx>n||ny<1||ny>n||mp[nx][ny]=='1') continue;
if(vis[nx][ny]==0){
vis[nx][ny]=1;
p.x=nx; p.y=ny; p.step=t.step+1;
q.push(p);
}
}
}
cout<<-1;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
cin>>mp[i][j];
}
if(mp[1][1]=='1'){
cout<<-1; return 0;
}
bfs();
return 0