AcWing刷题蓝桥杯专题突破-广度优先搜索-bfs(11)

Posted 戊子仲秋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AcWing刷题蓝桥杯专题突破-广度优先搜索-bfs(11)相关的知识,希望对你有一定的参考价值。

目录

写在前面:

题目:844. 走迷宫 - AcWing题库

题目描述:

输入格式:

输出格式:

输入样例:

输出样例:

解题思路:

代码:

AC !!!!!!!!!!

写在最后:


写在前面:

怎么样才能学好一个算法?

我个人认为,系统性的刷题尤为重要,

所以,为了学好广度优先搜索,为了用好搜索应对蓝桥杯,

事不宜迟,我们即刻开始刷题!

题目:844. 走迷宫 - AcWing题库

题目描述:

输入格式:

第一行包含两个整数 n 和 m。

接下来 n 行,每行包含 m 个整数(00 或 11),表示完整的二维数组迷宫。

输出格式:

输出一个整数,表示从左上角移动至右下角的最少移动次数。

数据范围:

1 ≤ n, m ≤ 100

输入样例:

5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

输出样例:

8

解题思路:

今天,我开始学习广度优先搜索,

如果说深度优先搜索是一直往下搜,触底反弹回溯,再继续搜索出所有情况,

那么广度优先是一层一层的搜索,

简单来说就是就是运用二叉树层序遍历的思想进行搜索,

就比如这道题,走迷宫,我们也可以用深度优先搜索去做,

但是题目要求的数据范围比较大,深度优先会超出时间限制,

所以这个时候就要用到广度优先搜索,

接下来是具体思路:

 我们需要从左上角到右下角,

找出他们的最短路径和,

运用广度优先的思想:

开始搜索:

继续往下搜索:

 红色的数字1,表示的是该坐标与起点距离是1,

层层记录距离,就能返回最短路径和,

继续搜索:

以此类推:

 我们就搜索到了最短的路径和,

那么这是怎么实现的呢?

就是利用队列先进先出的特性,

往下遍历的时候,将下一层的数据全部入队:

 然后就让该坐标出队,并将下一层入队:

 继续出队,然后入队:

 就能够达成我们广度搜索的条件往下搜索,

下面是代码实现:

代码:

//包好常用头文件
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

//用来存坐标
typedef pair<int, int> PII;

const int N = 110;

int n, m;

//队列
queue<PII> q;

//用来读入地图
int g[N][N];

//用来记录地图状态和层数(离初始位置的距离)
int dist[N][N];

//坐标偏移量
int dx[] = -1, 0, 1, 0;
int dy[] = 0, 1, 0, -1;

int bfs(int x, int y)

    //先把状态都置位-1
    memset(dist, -1, sizeof(dist));
    q.push(x, y);
    
    //起点
    dist[x][y] = 0;
    
    //如果队列不为空,就一直出队搜索
    while(!q.empty())
    
        //记录队头
        auto t = q.front();
        q.pop();
        for(int i = 0; i < 4; i++)
        
            //上下左右搜索
            int a = t.first + dx[i];
            int b = t.second + dy[i];
            
            //控制边界
            if(a < 1 || a > n || b < 1 || b > m) continue;
            if(g[a][b] != 0) continue;
            
            //如果走过,就不搜索了
            if(dist[a][b] > 0) continue;
            
            //入队
            q.push(a, b);
            
            //记录的路径和+1
            dist[a][b] = dist[t.first][t.second] + 1;
        
    
    //返回终点的路径和
    return dist[n][m];


int main()

    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++)
    
        for(int j = 1; j <= m; j++)
        
            scanf("%d", &g[i][j]);
        
    
    
    int res = bfs(1, 1);
    printf("%d\\n", res);
    return 0;

AC !!!!!!!!!!

写在最后:

以上就是本篇文章的内容了,感谢你的阅读。

如果喜欢本文的话,欢迎点赞和评论,写下你的见解。

如果想和我一起学习编程,不妨点个关注,我们一起学习,一同成长。

之后我还会输出更多高质量内容,欢迎收看。

洛谷刷题蓝桥杯专题突破-广度优先搜索-bfs(16)

目录

写在前面:

题目:P2895 [USACO08FEB]Meteor Shower S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目描述:

输入格式:

输出格式:

输入样例:

输出样例:

解题思路:

代码:

AC !!!!!!!!!!

写在最后:


写在前面:

怎么样才能学好一个算法?

我个人认为,系统性的刷题尤为重要,

所以,为了学好广度优先搜索,为了用好搜索应对蓝桥杯,

事不宜迟,我们即刻开始刷题!

题目:P2895 [USACO08FEB]Meteor Shower S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目描述:

输入格式:

共 M + 1 行,第 1 行输入一个整数 M,

接下来的 M 行每行输入三个整数分别为 Xi​, Yi​, Ti​。

输出格式:

贝西到达安全地点所需的最短时间,如果不可能,则为 −1。

输入样例:

4
0 0 2
2 1 2
1 1 2
0 3 5

输出样例:

5

解题思路:

看完题目,这道题大致的意思就是:

贝茜从起点开始找安全的位置,天上的流星不断往下砸,

我们可以通过广度优先搜索帮她搜索安全的位置,

我们先通过题目给出的样例模拟一下这个过程:

贝茜从起点出发,

每次能走四个方向,

但是我们需要先将流星会砸到的地方标记出来, 

如果贝茜走到被流星砸到的地方,证明那个位置是不能走的: 

第一个流星砸在(2, 1)........(补丁:这里漏了,还有一颗流星是砸在(0, 0) , 不过不影响结果)

 第二颗砸在(1, 1)

 第三颗砸在(0, 3)

 贝茜从起点出发:

继续走,如果走的是那两个地方,

就会被砸死:

 这样就成功躲过流星了:

 最后就返回5。

 那么,根据我们刚刚模拟的思路,

下面是代码实现:

代码:

//包好头文件
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef pair<int, int> PII;

int n = 0;

const int N = 310;

int g[N][N];
PII q[N * N];
int dist[N][N];
int star[N][N];//存流星砸到的点

int dx[] = -1, 0, 1, 0;
int dy[] = 0, 1, 0, -1;

int bfs()

    q[0] = 0, 0;
    dist[0][0] = 0;
    int head = 0;
    int tail = 0;
    while(head <= tail)
    
        auto t = q[head++];
        for(int i = 0; i < 4; i++)
        
            int a = t.first + dx[i];
            int b = t.second + dy[i];
            
            //控边界
            if(a < 0 || b < 0) continue;
            
            //走过的路不再走
            if(dist[a][b] > 0) continue;
            
            //如果流星已经砸了就走不了/被砸死
            if(dist[t.first][t.second] + 1 >= star[a][b]) continue;
            
            dist[a][b] = dist[t.first][t.second] + 1;
            q[++tail] = a, b;
            
            //如果发现走到的位置没有流星砸,返回
            if(star[a][b] > 1e9) return dist[a][b];
        
    
    return -1;


int main()

    scanf("%d", &n);
    memset(star, 0x3f, sizeof(star));
    while(n--)
    
        int x, y, t;
        scanf("%d %d %d", &x, &y, &t);
        star[x][y] = min(t, star[x][y]);//流星砸到的中心点
        for(int i = 0; i < 4; i++)
        
            int a = dx[i] + x;
            int b = dy[i] + y;
            
            if(a < 0 || a > 300 || b < 0 || b > 300) continue;
            
            star[a][b] = min(t, star[a][b]);//往外延伸的四个点
        
    
    int res = bfs();
    printf("%d", res);
    return 0;

AC !!!!!!!!!!

写在最后:

以上就是本篇文章的内容了,感谢你的阅读。

如果喜欢本文的话,欢迎点赞和评论,写下你的见解。

如果想和我一起学习编程,不妨点个关注,我们一起学习,一同成长。

之后我还会输出更多高质量内容,欢迎收看。

以上是关于AcWing刷题蓝桥杯专题突破-广度优先搜索-bfs(11)的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥杯算法竞赛系列第八章——提高篇之广度优先搜索(BFS)

广度优先搜索的实际应用

蓝桥杯——数学专题

蓝桥杯——动态规划专题

算法专题 之 广度优先搜索

面试刷题:广度优先搜索BFS | 第91期