bfs从原理上来讲就是在初始状态把所有可行的操作一一进行操作,通过不断的尝试找到目标状态,举个例子就好比在一个水池中扔入一颗石子会溅起水波水波不断地向各个空间移动最终到达目的状态,又好比走迷宫一般在每一个节点把上下左右都尝试一遍之后找到出口 因为bfs需要不断地储存状态,取出之前存放状态,进行操作,再次储存,我们不难想到用队来进行储存;
例题如下
1312 “Red and Black”
一个长方形的房间,铺着方形瓷砖,瓷砖为红色或黑色。一个人站在黑色瓷砖上,他可以按上、下、左、右方向移动到相邻的瓷砖。但他不能在红色瓷砖上移动,只能在黑色瓷砖上移动。编程计算他可以到达的黑色瓷砖的数量。
输入:第1行包含两个正整数W和H,W和H分别表示x方向和y方向上的瓷砖数量。W和H均不超过20。下面有H行,每行包含W个字符。每个字符表示一片瓷专的颜色。用符号表示如下:“。”表示黑色瓷砖;“#”表示红色瓷砖;“@”代表黑色瓷砖上的人,在数据集中只出现一次。
输出:一个数字,这个人从初始瓷砖能到达的瓷砖总数量(包括起点)。
(题目来源hduoj)
首先我们需要一个二维数组来储存初始各个转块的情况,再者我们需要储存横向个数和纵向格个数,再者我们需要一个结构体储存人的当前坐标
char room[23][23];
int Wx,hY;
struct node
{
int x;
int y;
};
int numb;//记录可走的砖块个数
其次我们需要对当前状态进行移动操作
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};//进行移动操作
再来因为一个状态我们需要四次移动尝试所以我们利用循环,然后再判断移动后的点是否是可行的
如果可行存入队中,同时我们需要两个结构体一个记录当前坐标一个记录移动后的坐标(start,next)
for(int i=0;i<4;i++)
{
next.x=start.x+dir[i][0];
next.y=start.y+dit[i][1];
if(next.x>=0&&next.x<Wx&&next.y>=0&&next.y<Hy&&room[next.x][next.y]=='.')//判断当前状态是否可行
{
numb++;
room[next.x][next.y]='#';//将走过的砖头改为#防止重复
q.push(next);
}//如果可行讲此状态入队,.改为#表示已经走过
然后我们再从对列中取出一个元素进行操作即可
完整代码如下
#include<bits/stdc++.h>
using namespace std;
struct node
{
int x;
int y;
};
int Wx,Hy,num;
#define CHEACK(x,y)(x<Wx&&x>=0&&y<Hy&&y>=0)
char room[23][23];
int dior[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
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<<"x="<<start.x<<"y="<<start.y<<endl;
for(int i=0;i<4;i++)
{
next.x=start.x+dior[i][0];
next.y=start.y+dior[i][1];
if(CHEACK(next.x,next.y)&&room[next.x][next.y]=='.')
{
room[next.x][next.y]='#';
q.push(next);
num++;
}
}
}
}
int main()
{
cin>>Wx>>Hy;
int dx,dy;
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;
}
}
}
bfs(dx,dy);
cout<<num<<endl;
}