算法-BFS广度优先搜索
BFS广度优先搜索
DFS深度优先搜索参见 DFS
代码分析
常用代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII; //pair<int,int> 是将两个int类型的数合为一个,本质上是结构体
queue<PII> q; //创建一个队列,名为q,类型是pair<int,int>(上方定义为PII)
PII temppair; //创建临时pair以储存从队列弹出的数据
int Map[N][N]; //创建地图,注意不要写map
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int len; // *有时候会用到,比如长草那道题,需要用来判断这次扩张是否结束。
/*
dx和dy数组是把Map地图区域划分成如下的两个轴:
—————————————————> y
|
|
|
↓
x
将二维数组arr[n][m]看成n*m的,一个单位为1的网格
左上角是(0,0),往下走是(1,0),往右走是(0,1)
dx[0]=1,dy[0]=0 表示向下,其余同理
*/
bool pd(int x,int y)
{
if(//通常最基本的条件是不能越界)
return false;
if(//也可能判断取到的地方有没有去过)
return false;
return true;
}
void bfs()
{
while(!q.empty)
{
temppair = q.front(); //取队列第一个值
q.pop(); //并把它删除
for(int i=0;i<4;i++)
{
int nowx=temppair.first+dx[i]; //从这个节点开始向上下左右取数
int nowy=temppair.second+dy[i];
if(pd(nowx,nowy)) //判断那个位置能不能满足要求
{
//满足要求后..
}
}
}
}
int main()
{
// 函数主体,包括读入数据,创建地图等...
int x1,y1; //假定这里读入一个初始坐标
q.push({x1,y1}); //把它压入队列
bfs();
// 输出...
return 0;
}
例题分析
求细胞数量
题干
题目描述
一矩形阵列由数字 0 到 9 组成,数字 1 到 9 代表细胞,细胞的定义为沿细胞数字上下左右若还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。
输入格式
第一行两个整数代表矩阵大小 n 和 m。
接下来 n 行,每行一个长度为 m 的只含字符 0
到 9
的字符串,代表这个 n \times m 的矩阵。
输出格式
一行一个整数代表细胞个数。
样例 #1
样例输入 #1
4 10
0234500067
1034560500
2045600671
0000000089
样例输出 #1
4
提示
数据规模与约定
对于 100% 的数据,保证 1 <=n,m <=100。
代码
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
PII temppair;
queue<PII> q;
int Map[105][105],mark[105][105];
int n,m;
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
bool pd(int x,int y)
{
if(Map[x][y]==0) //在本题中0是非细胞数字
return false;
if(x<1||x>n||y<1||y>m) //越界检测
return false;
if(mark[x][y]==1) //已经去过的标记检测
return false;
return true;
}
void bfs()
{
while(!q.empty())
{
temppair=q.front(); //取队首元素
q.pop(); //删除第一个元素
for(int i=0;i<4;i++)
{
int nowx=temppair.first+dx[i];
int nowy=temppair.second+dy[i];
if(pd(nowx,nowy))
{
q.push({nowx,{nowy}}); //如果是细胞数字,并且没有越界,就把这个位置压入队列
mark[nowx][nowy]=1; //并且做上标记
}
}
}
}
int main()
{
int cnt=0;
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%1d",&Map[i][j]); //!!!特别注意!!! scanf可以控制输入的数字位数,比如这里%1d就是输入1位数,题目给的数字都是没有空格的
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(Map[i][j]!=0&&mark[i][j]!=1) //从左上角开始依次遍历
{
mark[i][j]=1;
q.push({i,j});
bfs();
cnt++;
}
}
cout<<cnt;
return 0;
}
马的遍历
题目描述
有一个 n * m 的棋盘,在某个点 $(x, y)$ 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入格式
输入只有一行四个整数,分别为 n, m, x, y。
输出格式
一个 n * m的矩阵,代表马到达某个点最少要走几步(不能到达则输出 -1)。
样例 #1
样例输入 #1
3 3 1 1
样例输出 #1
0 3 2
3 -1 1
2 1 4
代码
#include <bits/stdc++.h>
using namespace std;
#define N 500
typedef pair<int,int> PII;
PII temp;
queue<PII> q;
int dx[8]={1,2,2,1,-1,-2,-2,-1}; //马走日
int dy[8]={-2,-1,1,2,2,1,-1,-2};
int n,m,x2,y2; //行 列 起x 起y
long long Map[N][N]={0},done[N][N]={0};
int len; //用以判断是否结束了这次扩张
bool pd(int x,int y)
{
if(x<1||x>n||y<1||y>m)
return false;
if(done[x][y]==1)
return false;
return true;
}
void bfs()
{
int step=1;
while(!q.empty())
{
temp=q.front();
q.pop();
for(int i=0;i<8;i++)
{
int nowx=dx[i]+temp.first;
int nowy=dy[i]+temp.second;
if(pd(nowx,nowy))
{
Map[nowx][nowy]=step;
done[nowx][nowy]=1;
q.push({nowx,nowy});
}
}
len--;
if(len==0)
{
step++;
len=q.size();
}
}
}
int main()
{
cin>>n>>m>>x2>>y2;
q.push({x2,y2});
done[x2][y2]=1;
bfs();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(Map[i][j]==0 && done[i][j]==0)
Map[i][j]=-1;
printf("%-5lld",Map[i][j]);
}
cout<<'\n';
}
return 0;
}
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 VR小杰
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果