首页 > 其他 > 详细

BFS.1

时间:2020-10-04 19:58:10      阅读:31      评论:0      收藏:0      [点我收藏+]

1.BFS

  • 大概分为两种题目:
  • 对于地图本身操作(最小步数)或者说二维矩阵上面的距离问题

2.边权唯一和flood fill模型:

3.bfs的特点:

  • 求“最小或者求最短”
  • 求迭代,“不会爆炸”

4.flood fill

  • 在线性时间内,找到某个点的连通块

t1:细胞,最基本的floodfill

代码如下:

  • 技术分享图片
    #include <stdio.h>
    #include <algorithm>
    #include <cstring>
    
    #define x first
    #define y second
    
    using namespace std;
    
    typedef pair<int,int> PII;
    
    const int maxn=1010,maxm=1010*1010;
    
    char g[maxn][maxn];
    bool st[maxn][maxn];
    int n,m;
    PII q[maxm];
    
    inline void bfs(int sx,int sy)
    {
        int head=0,tail=0;
        q[0]={sx,sy};
        st[sx][sy]=true;
        while(head<=tail)
        {
            PII t=q[head++];
            for(int i=t.x-1;i<=t.x+1;i++)
                 for(int j=t.y-1;j<=t.y+1;j++)
                 {
                     if(i==t.x&&j==t.y) continue;
                     if(i<0||i>=n||j<0||j>=m) continue;
                     if(st[i][j]||g[i][j]==.) continue;
                     st[i][j]=true;
                     q[++tail]={i,j};
                     
                 }    
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++) scanf("%s",g[i]);
        int cnt=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
        {
            if(!st[i][j]&&g[i][j]==W)
            {
                bfs(i,j);
                cnt++;
            }
        }
        printf("%d",cnt);
        return 0;
    }
    View Code

    注意编程细节:

  1. 对于字符串题目,我们可以使用scanf直接读入一行,但同时就需要注意从0开始,判断出边界就是i>=n
  2. 注意是四联通(有边相连)还是八联通(有点相连)
  3. 如果是四联通写数组,八联通的话就写pair
  4. 注意#define x frist 的形式来写
  5. 对于这样子的话,只能用数组来模拟队列,并且将q定义成相应形式就可

T2城堡

  • 四维模型
  • 增加返回值就可
  • 一般需要注意的(重复遍历,有墙,超出边界)
  • 四联通就定义dx,dy数组

T3判断型:

  • 增加伴随变量就可
  • 注意判断有高有矮一定要注意是在越界之后才判断
  • 存在及可能是山峰也可能是山谷的情况

4.单源最短路:

  • 在每条边权都相等的情况下,一次bfs求出单元最短路的距离

T1迷宫:

技术分享图片
#include <stdio.h>
#include <algorithm>
#include <cstring>

#define x first
#define y second
using namespace std;

typedef pair<int,int> PII;
const int maxn=1010,maxm=1010*1010;

int g[maxn][maxn];
PII q[maxm];
PII pre[maxn][maxn];
int n,m;

void bfs(int sx,int sy)
{
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
    int head=0,tail=0;
    memset(pre,-1,sizeof(pre));
    q[0]={sx,sy};
    pre[sx][sy]={0,0};//pre数组也需要初始化
    while(head<=tail)
    {
        PII t=q[head++];
        for(int i=0;i<4;i++)
        {
            int a=t.x+dx[i],b=t.y+dy[i];
            if(pre[a][b].x!=-1) continue;
            if(a<0||a>=n||b<0||b>=n) continue;
            if(g[a][b])continue;
            q[++tail]={a,b};
            pre[a][b]=t;
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++) scanf("%d",&g[i][j]);
    bfs(n-1,n-1);
    PII end(0,0);
    while(true)
    {
        printf("%d %d\n",end.x,end.y);
        if(end.x==n-1&&end.y==n-1) break;
        end=pre[end.x][end.y];
    }
    return 0;
}
View Code
  • 本题经典模型:使用pre数组来存储上一个是从哪一步转移过来的
  • 同时,为了节省空间不倒序存储,我们使用反向遍历的技巧【原则:搜索顺序,逆向思维】
  • 从n-1,n-1开始搜到0,0;同时用pre转移到上一个去就可;
  • 剩下的就没有东西了
  • 注意细节和格式

T2

  • 类型可以看成对地址的解释方式;
  • 在结构体内,所有的数据都会按照结构单元连续的放在一起
  • 对齐原理:加入int 4字节,char1字节,最后变成的是八字节
  • 本题改变了dx,dy数组,其余不变
  • 代码:
  • 技术分享图片
    #include <stdio.h>
    #include <algorithm>
    #include <cstring>
    
    #define x first
    #define y second
    using namespace std;
    
    typedef pair<int,int> PII;
    
    const int maxn=1010,maxm=1010*1010;
    int n,m;
    char g[maxn][maxn];
    PII q[maxm];
    int dis[maxn][maxn];
    
    inline int bfs()
    {
        int dx[]={1,2,2,1,-1,-2,-2,-1};
        int dy[]={2,1,-1,-2,-2,-1,1,2};
        int sx,sy;
        for(int i=0;i<n;i++)
             for(int j=0;j<m;j++)
            {
                if(g[i][j]==K)
                {
                    sx=i,sy=j;
                    break;
                }
            }
        int head=0,tail=0;
        q[0]={sx,sy};
        memset(dis,-1,sizeof(dis));
        dis[sx][sy]=0;
        while(head<=tail)
        {
            PII t=q[head++];
            for(int i=0;i<8;i++)
            {
                int a=t.x+dx[i],b=t.y+dy[i];
                if(dis[a][b]!=-1) continue;
                if(a<0||a>=n||b<0||b>=m) continue;
                if(g[a][b]==*) continue;
                if(g[a][b]==H) return dis[t.x][t.y]+1;
                dis[a][b]=dis[t.x][t.y]+1;
                q[++tail]={a,b};
            }
        }
    }
    int main()
    {
        scanf("%d%d",&m,&n);
        for(int i=0;i<n;i++) scanf("%s",g[i]);
        printf("%d",bfs());
        return 0;
    }
    View Code

     

T3

  • 这题是类比dij
  • 这个时候我们发现,这个距离是单调递增的
  • 在边权相同的情况下,那么bfs的队列就变成了单调递增
  • 最后一题:更变形式,二维专一维,只是更变了写法而已;注意跳的点一定要在范围以内
  • 【注意,再这样数轴类型的题目当中,如果没有对于bfs的层数限制,一定要合理的推导出一个上限来限制就可】

 

BFS.1

原文:https://www.cnblogs.com/ILHYJ/p/13767715.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!