2024年寒假算法班集训day10-知识总结及题解(广度优先搜索)

概念

广度优先搜索(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 结构体来存储每个节点的位置和步数,以及两个数组 mpvis 分别用于存储矩阵和标记节点是否已被访问。

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 结构体来存储每个节点的位置和步数,以及两个数组 mpvis 分别用于存储矩阵和标记节点是否已被访问。

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<
  • 48
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值