暑假学习——队列与BFS

BFS和队列,这两种东西的实现方式非常像,以hdu1312为例

此题中我们需要从起点开始,不断向外围扩散,扩散的过程中所有第一次遇到的黑砖都是我们需要记录的对象。

那么就有如下三种解释
第一种图形解释请添加图片描述

第二种,树状图形解释
请添加图片描述

第三种,根据树状图形来的文字解释
起点1入队 {1}
第一步:1出队,2,3入队 {2,3}
第二步:2,3出队4 5 6和7 8分别入对{4,5,6,7,8}
第三步:4出 9入 5出10入 6出11入 8出 7出13 12入{9,10,11,13,12}
第四步:13出 12出 9出 10出14入 11出15入{14,15}
第五步:14出 15出{}

每一步向下,应该有自己的检索方式,这种检索方式+扩散+队列一般就能构成一个BFS的代码

接下来附上此题代码
首先,我们已经明确这个扩散的过程,那么检索方式就如第一个图中,上下左右去寻找是“黑色砖”的点。

#include <iostream>
#include <queue>
using namespace std;
char room[23][23];
int WX,HY;
int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
#define CHECK(x,y) (x>=0&&x<=WX&&y>=0&&y<=HY)
struct node
{
    int x,y;
};
int num;
void BFS(int dx,int dy)
{
    num=1;
    queue <node> q;
    node start,next;
    start.x=dx;
    start.y=dy;
    q.push(start);
    while(!q.empty())
    {
        start=q.front();
        q.pop();
        cout<<start.x<<" "<<start.y<<endl;
        for(int i=0;i<4;i++)
            {
                next.x=start.x+dir[i][0];
                next.y=start.y+dir[i][1];
                if(CHECK(start.x,start.y)&&room[next.x][next.y]=='.')
                {
                    num++;
                    q.push(next);
                    room[next.x][next.y]='#';
                }
            }
    }

}


int main()
{
    int t,dx,dy;
    for(cin>>t;t;t--)
    {
        cin>>WX>>HY;
        if(WX==0&&HY==0)
        {
            cout<<0<<endl;
            continue;
        }
        for(int i=0;i<WX;i++)
        {
            for(int j=0;j<HY;j++)
            {
                cin>>room[i][j];
                if(room[i][j]=='@')
                {
                    dx=i;
                    dy=j;
                }
            }
        }
        num=0;
        BFS(dx,dy);
        cout<<num<<endl;
    }
}

分段解释一下
这些是前期的准备
用于记录砖的信息
char room[23][23];
int WX,HY;
用于移动
int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
用于检查
#define CHECK(x,y) (x>=0&&x<=WX&&y>=0&&y<=HY)
用于标记位置
struct node
{
int x,y;
};
用于记录最终的answer
int num;

用于BFS
void BFS(int dx,int dy)
{
num=1;
queue q;/队列由此体现/
node start,next;
start.x=dx;
start.y=dy;
q.push(start);/入队/
while(!q.empty())
{
start=q.front();
q.pop();/出队/
cout<<start.x<<" "<<start.y<<endl;/用于验证/
for(int i=0;i<4;i++)
{
next.x=start.x+dir[i][0];/移动/
next.y=start.y+dir[i][1];/移动/
if(CHECK(start.x,start.y)&&room[next.x][next.y]==’.’)/判断是否符合检索要求/
{
num++;
q.push(next);/入队/
room[next.x][next.y]=’#’;
}
}
}

}

注意:
1.一个出队后对应一次操作,也就是遍历他的上下左右。
2.
next.x=start.x+dir[i][0];/移动/
next.y=start.y+dir[i][1];/移动/
不要写成
start.x+=dir[i][0]
start.y+=dir[i][1]
这样就不是以一个点为中心向上下左右去遍历了,就变成画圈了,因为中心点一直在变。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值