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]
这样就不是以一个点为中心向上下左右去遍历了,就变成画圈了,因为中心点一直在变。