ACM模板 BFS广搜

描述

广度优先搜索算法(英语:Breadth-First-Search,缩写为BFS),又译作宽度优先搜索,或横向优先搜索,是一种图形搜索算法。简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。广度优先搜索的实现一般采用open-closed表。源于:维基百科

应用

图最短路问题

问题描述:在一个二维矩阵图中,起点为a,终点为r,x为守卫(意味着你要花费1个单位时间解决守卫),#代表着墙,‘.’代表可以走,花费一个单位时间;
输入:第一行输入n,m代表一个nm的矩阵,然后接下来的nm个数据就是这个矩阵的元素,(循环这个过程)
输出:a到r的最短时间,如果无法达到,则输出-1

代码展示:

#include <bits/stdc++.h>
using namespace std;
const int maxm = 500;
const int maxn = 500;
char Map[maxm][maxn];                     //用于存储矩阵元素
int f[4][2] = {1, 0, 0, 1, -1, 0, 0, -1}; //代表着四个方向
int n, m, ans;
struct node
{
    int x, y, step; //坐标和步数即时长
} now, nextt;       //now是当前状态,nextt是下一个状态

bool judge(int xx, int yy) //判断函数,判断下一步是否可以走
{
    return (xx >= 0 && xx < n && yy >= 0 && yy < m && Map[xx][yy] != '#');
}

int BFS(int x, int y)
{
    queue<node> q;
    Map[x][y] = '#'; //令传进来的点变成墙,也就是这个点已走过
    now.x = x;
    now.y = y;
    now.step = 0;
    q.push(now); //当前状态入队列
    while (!q.empty())
    {
        now = q.front(); //将now设为队列中的第一个元素
        q.pop();         //弹出now代表的元素,为nextt做准备
        for (int i = 0; i < 4; i++)
        {
            nextt.x = now.x + f[i][0];
            nextt.y = now.y + f[i][1];
            if (judge(nextt.x, nextt.y)) //下一步可以走
            {
                nextt.step = now.step + 1;
                if (Map[nextt.x][nextt.y] == 'r') //判断结束
                    return nextt.step;
                else if (Map[nextt.x][nextt.y] == 'x')
                    nextt.step++;            //解决守卫,时间加1
                q.push(nextt);               //下一个状态入队
                Map[nextt.x][nextt.y] = '#'; //标为已走
            }
        }
    }
    return -1;
}
int main()
{
    int xb, yb; //开始坐标
    while (~scanf("%d%d", &n, &m))
    {
        for (int i = 0; i < n; i++)
        {
            scanf("%s", Map[i]);
            for (int j = 0; j < m; j++)
            {
                if (Map[i][j] == 'a')
                {
                    xb = i;
                    yb = j;
                }
            }
        }
        ans = BFS(xb, yb);
        cout << ans << endl;
    }
    return 0;
}

图联通块问题

简要问题描述:对于一个nm的矩形土地,下面有可能具有油田,而对于联通在一起的油田(上下左右左上…等八个方向),可以称为一块;给你一个矩形地图,你可以判断出有几块油田吗?如:@代表油田
@@&&&
@&@&&
&&&&&&
@&&&&
有两块;
输入:第一行输入n,m代表一个n
m的矩阵,然后接下来的n*m个数据就是这个矩阵的元素,(循环这个过程)
输出:油田的块数
代码展示:(其实和上面的差不多)

#include <bits/stdc++.h>
using namespace std;
const int maxm = 500;
const int maxn = 500;
char Map[maxm][maxn];                                                 //用于存储矩阵元素
int f[8][2] = {1, 0, 0, 1, -1, 0, 0, -1, 1, 1, 1, -1, -1, 1, -1, -1}; //代表着四个方向
int n, m, ans;
struct node
{
    int x, y; //坐标
} now, nextt; //now是当前状态,nextt是下一个状态

bool judge(int xx, int yy) //判断函数,判断下一步是否可以走
{
    return (xx >= 0 && xx < n && yy >= 0 && yy < m && Map[xx][yy] != '&');
}

void BFS(int x, int y)
{
    queue<node> q;
    Map[x][y] = '&'; //令传进来的点变成墙,也就是这个点已走过
    now.x = x;
    now.y = y;
    q.push(now); //当前状态入队列
    while (!q.empty())
    {
        now = q.front(); //将now设为队列中的第一个元素
        q.pop();         //弹出now代表的元素,为nextt做准备
        for (int i = 0; i < 8; i++)
        {
            nextt.x = now.x + f[i][0];
            nextt.y = now.y + f[i][1];
            if (judge(nextt.x, nextt.y)) //下一步可以走
            {
                q.push(nextt);               //下一个状态入队
                Map[nextt.x][nextt.y] = '&'; //标为已走
            }
        }
    }
}
int main()
{
    int cnt; //联通块的个数
    while (~scanf("%d%d", &n, &m))
    {
        cnt = 0; //初始化
        for (int i = 0; i < n; i++)
        {
            scanf("%s", Map[i]);
        }
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                if (Map[i][j] == '@')
                {
                    BFS(i, j);
                    cnt++;
                }
            }
        }
        cout<<cnt<<endl;
    }
    return 0;
}

创作不易,点个赞支持一下呗!
在这里插入图片描述

发布了41 篇原创文章 · 获赞 20 · 访问量 8635

猜你喜欢

转载自blog.csdn.net/zmx2473162621/article/details/104044618