DFS与BFS的实现
前言
DFS和BFS都是搜索的一种方式,两种不同的搜索方向对应着不同的情景,但无论怎么样,他们都是暴力搜索的思路,都能覆盖到全部的情况,下面讲简单的阐述一下他们应用的场合和实现的方式.
DFS
他叫什么?
深度优先搜索
主要的内容是什么?
如果把每一条路径分成好几层,但找到其中的一层时,他会选择寻找下一层的位置,而不是继续探索同一层的其他位置.
当需要寻找某两点之间的路径数的时候,就可以选择DFS
例题
P1605迷宫
题目描述
给定一个 N × M N \times M N×M 方格的迷宫,迷宫里有 T T T 处障碍,障碍处不可通过。
在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。
输入格式
第一行为三个正整数 N , M , T N,M,T N,M,T,分别表示迷宫的长宽和障碍总数。
第二行为四个正整数 S X , S Y , F X , F Y SX,SY,FX,FY SX,SY,FX,FY, S X , S Y SX,SY SX,SY 代表起点坐标, F X , F Y FX,FY FX,FY 代表终点坐标。
接下来 T T T 行,每行两个正整数,表示障碍点的坐标。
输出格式
输出从起点坐标到终点坐标的方案总数。
样例 #1
样例输入 #1
2 2 1
1 1 2 2
1 2
样例输出 #1
1
提示
对于 100 % 100\% 100% 的数据, 1 ≤ N , M ≤ 5 1 \le N,M \le 5 1≤N,M≤5, 1 ≤ T ≤ 10 1 \le T \le 10 1≤T≤10, 1 ≤ S X , F X ≤ n 1 \le SX,FX \le n 1≤SX,FX≤n, 1 ≤ S Y , F Y ≤ m 1 \le SY,FY \le m 1≤SY,FY≤m。
思路
(最最最最典型的DFS)
可以使用一个方位数组,用for循环来实现位置的移动,最后只需要注意记录次数就行了
代码实现
#include<iostream>
using namespace std;
int map[11][11]={};
int begin1_x,begin1_y;
int end_x,end_y;
int n,m,t;
bool flag[11][11]={};
int sx[5]={0,1,-1,0,0};
int sy[5]={0,0,0,1,-1};
int sum=0;
void dfs(int begin_x,int begin_y)
{
if(begin_x==end_x && begin_y==end_y)
{
sum++;
return;
}
int now_x=0,now_y=0;
flag[begin_x][begin_y]=1;
for(int i=1;i<=4;i++)
{
now_x=begin_x+sx[i];
now_y=begin_y+sy[i];
if(now_x<1 || now_x>n || now_y<1 || now_y>m || map[now_x][now_y]==1 ||flag[now_x][now_y]==1) continue;
flag[now_x][now_y]=1;
dfs(now_x,now_y);
flag[now_x][now_y]=0;
}
}
int main()
{
cin>>n>>m>>t;
cin>>begin1_x>>begin1_y>>end_x>>end_y;
for(int i=1;i<=t;i++)
{
int a,b;
cin>>a>>b;
map[a][b]=1;
}
dfs(begin1_x,begin1_y);
cout<<sum<<endl;
return 0;
}
BFS
他又叫什么?
深度优先搜索
主要的内容是什么?
在找到某个位置的时候,他会先记录下这个位置来接下来要走的地方,但是先放着,先去探索同一层的其他位置.在本层全部探索完毕之后,他才会走之前已经记录下来的位置.
例题
马的遍历
题目描述
有一个 n × m n \times m n×m 的棋盘,在某个点 ( x , y ) (x, y) (x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入格式
输入只有一行四个整数,分别为 n , m , x , y n, m, x, y n,m,x,y。
输出格式
一个 n × m n \times m n×m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 − 1 -1 −1)。
样例 #1
样例输入 #1
3 3 1 1
样例输出 #1
0 3 2
3 -1 1
2 1 4
提示
数据规模与约定
对于全部的测试点,保证 1 ≤ x ≤ n ≤ 400 1 \leq x \leq n \leq 400 1≤x≤n≤400, 1 ≤ y ≤ m ≤ 400 1 \leq y \leq m \leq 400 1≤y≤m≤400。
思路
由于马的移动方式是已知的,所以用一个特殊的方位数组来定义马的移动即可.
代码实现
#include<iostream>
#include<queue>
#include<iomanip>
using namespace std;
const int maxn=401;
int map[maxn][maxn]={};
int n,m,x,y;
struct p
{
int x,y;
};
int flag[maxn][maxn]={};
queue <p> q;
queue <p> q_copy;
int sx[9]={0,1,2,2,-1,-2,1,-2,-1};
int sy[9]={0,2,1,-1,2,1,-2,-1,-2};
void bfs(int times)
{
if(q.empty()) return ;
while(!q.empty())
{
p p1=q.front();
q.pop();
int x=p1.x;
int y=p1.y;
for(int i=1;i<=8;i++)
{
int now_x=x+sx[i];
int now_y=y+sy[i];
if(now_x<1 || now_x>n || now_y<1 || now_y>m || flag[now_x][now_y]!=0) continue;
flag[now_x][now_y]=times;
p p2;
p2.x=now_x,p2.y=now_y;
q_copy.push(p2);
}
}
q.swap(q_copy);
bfs(++times);
}
int main()
{
cin>>n>>m>>x>>y;
p P;
P.x=x,P.y=y;
q.push(P);
flag[x][y]=-1;
bfs(1);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(flag[i][j]==0) flag[i][j]=-1;
}
}
flag[x][y]=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cout<<left<<setw(4)<<flag[i][j];
}
cout<<endl;
}
return 0;
}
小结
- DFS和BFS都是搜索的一种方式,在有时是都都可以用的,在特殊的场合只能用其中一种,只需要我们根据题目的特点去进行选择即可.
- 在实现的时候经常会用到方位数组,判断数组,栈等.