<span style="font-size:24px;"><strong>第一个例子:计算二维字符数组的块数,1表示有效,0表示无效</strong></span>
#include<cstdio>
#include<queue>
using namespace std;
const int maxn=1010;
struct node{
int x,y;//位置(x,y)
}Node;
int n,m;//矩阵大小为n*m
int matrix[maxn][maxn];//01矩阵
bool inq[maxn][maxn]={false};//记录位置(x,y)是否已经入过队
int X[4]={0,0,1,-1};//增量数组
int Y[4]={1,-1,0,0};//两个增量数组可以表示方向
//在一次BFS判断该结点是否需要访问的函数
//如果这个点越过了边界,或这个点是0,或这个点已经入过队了,(在那次入队将必定会进行遍历),就返回false,表示这个点无需再访问
//如果这个点是1且没有入过队,就说明要访问!
bool judge(int x,int y){//判断坐标(x,y)是否需要访问
//越界返回false
if(x>=n||x<0||y>=m||y<0) return false;
//当前位置为0或者(x,y)已经入过队,返回false
if(matrix[x][y]==0||inq[x][y]==true) return true;//如果当前元素为0或者当前元素已经入过队,也置为0
//以上都不满足,返回true
return true;
}
//是在BFS中用到judge()
//BFS函数访问位置(x,y)所在的块,并进行扩展,这个BFS需要参数的,将该块中所有的1的inq都置为true,并且入队
void BFS(int x,int y){//调用到这个函数的时候当前点必须是1
queue<node> Q;//定义队列
Node.x=x;Node.y=y;//当前结点的坐标为(x,y)
Q.push(Node);//将结点Node入队
while(!Q.empty()){//这个循环将扩张出一个块
node top=Q.front();//取出队首元素
Q.pop();//队首元素出队
for(int i=0;i<4;i++){//循环4次,看一下四个相邻点的情况.这里用到了增量数组
int newX=top.x+X[i];
int newY=top.y+Y[i];
if(judge(newX,newY)){//如果新位置(newX,newY)需要访问。这用到judge,应该是判断在本次BFS有一些重复遍历到的已经入队的点。恩是这样的
//设置Node的坐标wei(newX,newY)需要访问
Node.x=newX,Node.y=newY;
Q.push(Node);//将结点Node加入队列
inq[newX][newY]=true;//设置位置(newX,newY)已入过队列
}
}
}
}
int main(){
scanf("%d%d",&n,&m);//n行m列的矩阵
//读入矩阵
for(int x=0;x<n;x++){
for(int y=0;y<m;y++){
scanf("%d",&matrix[x][y]);
}
}
int ans=0;//存放块数
//注意是枚举每一个位置
for(int x=0;x<n;x++){//这个地方是不需要考虑边界的,边界问题留给每一个点的时候查看相邻结点考虑
for(int y=0;y<m;y++){
//如果元素为1,且未入过队。注意,如果入过队,必定已经属于某一个块了,那个块必定已经BFS遍历完成了。所以没有必要做重复功
if(matrix[x][y]==1&&inq[x][y]==false){//这里如果已经入过队说明这个点所在的块已经被完成了
ans++;//表示块数会增加1。因为遇到了一个不属于任何已发现的块的一个1,无论其是否孤立,都是一个新的块
BFS(x,y);//访问整个块,将该块所有1的inq都标记为true,而且要入队等等
}
}
}
return 0;
}
第二个例子:计算从起点到终点的最小步数
//这题是字符型矩阵,必须过滤掉每行后面的换行符!
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int maxn=100;
struct node{
int x,y;
int step;//step表示从起点S到达该位置的最小步数(即层数)
}Node,S,T;//S为起点,T为终点
int n,m;//n为行,m为列
char maze[maxn][maxn];//将存储迷宫信息
bool inq[maxn][maxn]={false};//记录位置(x,y)是否已经入过队
int X[4]={0,0,1,-1};
int Y[4]={1,-1,0,0};
//检验位置(x,y)是否有效
bool judge(int x,int y){
if(x>=n||y>=n||x<0||y<0)return false;
if(maze[x][y]='*'||inq[x][y]==true) return false;//如果是墙壁或者已经入过队,这个点也不用访问了!
return true;
}
int BFS(){//这个不需要参数因为只有一个起点
queue<node> q;//定义队列
q.push(S);//先将起点S入列
while(!q.empty()){
node top=q.front();//取出队首元素出列
q.pop();//队首元素出队
//如果这个结点刚好是终点,直接返回最少步数
if(top.x==T.x&&top.y==T.y){//直到返回到达终点,就返回层数
return top.step;//直接返回这一个数的的层数
}
for(int i=0;i<4;i++){//循环四次得到4个临近点
int newX=top.x+X[i];
int newY=top.y+Y[i];
if(judge(newX,newY)){//位置(newX,newY)有效,怎样有效是看是否是边界,是否是平地,是否不曾入队过(因为如果入队了的话,后面必将)
//设置Node的坐标
Node.x=newX,Node.y=newY;
Node.step=top.step+1;//Node层数为top的层数加1
q.push(Node);//入队,层数加1
inq[newX][newY]=true;//标记(newX,newY)已经加入队列
}
}
}
return -1;//无法到达终点T时返回-1
}
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
getchar();//必须过滤掉每行后面的换行符!
for(int j=0;j<m;j++){
maze[i][j]=getchar();
}
maze[i][m+1]='\0';//这里不太懂,有必要吗
}
scanf("%d%d%d%d",&S.x,&S.y,&T.x,&T.y);
S.step=0;//初始化起点的层数为0,即S到S的最下步数为0
printf("%d\n",BFS());
return 0;
}