1.前言:
得做些努力,先对搜索的题目下手,希望能有进步。
bfs应该是一种层次搜索,它是通过借助队列实现的。bfs一般可以解决最优,最快情况的问题。bfs的缺点就是占用的空间太大。宽度优先搜索可以解决最短路径、最少操作之类的题目,宽搜的过程中需要将已经访问过的状态保存起来,就可以很好的做到从近到远的搜索。
dfs应该是深度搜索,类似于树的先序搜索,它是通过递归来实现的。dfs可以解决有没有解的问题,能不能走出迷宫。
2.题型
1.地图迷宫
(1)八连通块问题(HDOJ1214,POJ2386)
https://blog.csdn.net/qq_37360631/article/details/77104082
(2)迷宫的最短路径BFS,并输出最短路径
http://blog.csdn.net/qq_37360631/article/details/76862479
(3)迷宫的最少拐弯数BFS(HDOJ1728)
http://blog.csdn.net/qq_37360631/article/details/76999765
(4)深度优先搜索过程中的剪枝
一个结论:起始点
(
x
,
y
)
(x,y)
(x,y)和终点
(
d
x
,
d
y
)
(dx,dy)
(dx,dy),那么
a
b
s
(
x
−
y
)
+
a
b
s
(
d
x
−
d
y
)
abs(x-y)+abs(dx-dy)
abs(x−y)+abs(dx−dy)的奇偶性和走的步数的奇偶性相同。
https://blog.csdn.net/qq_37360631/article/details/77017766
(5)记忆化搜索+BFS+剪枝
https://blog.csdn.net/qq_37360631/article/details/77018154
(6)DFS+回溯,打印出所有上升的情况
https://blog.csdn.net/qq_37360631/article/details/77030973
(7)DFS+回溯,字符串搜索,找出满足条件的一个解
https://blog.csdn.net/qq_37360631/article/details/77045227
(8)DFS+回溯,素数打表,素数环问题
https://blog.csdn.net/qq_37360631/article/details/77053502
(9)DFS+翻转棋盘棋子,使全部正面朝上
https://blog.csdn.net/qq_37360631/article/details/77899275
(10)DFS,蓝桥杯地宫取宝,要求从起点到终点恰好取k个礼物(每次取礼物必须满足一定条件),问一共有多少种方法取。
https://blog.csdn.net/qq_37360631/article/details/79766430
(11)DFS+vector,查询一个图中每个结点的父节点。
https://blog.csdn.net/qq_37360631/article/details/79978030
(12)DFS+剪枝,将一系列的小木棍拼成一个长木棍,要求每个长木棍长度相同。(还是不是很清楚…)
https://blog.csdn.net/qq_37360631/article/details/80149802
(13)DFS+回溯,遇到墙面可以选择新的方向,问从起点到终点最少可以转几次方向到达。
https://blog.csdn.net/qq_37360631/article/details/81627951
(14)BFS,将每次更新起点和终点,用N次BFS求和就是结果。
https://blog.csdn.net/qq_37360631/article/details/81630220
(15)DFS+SET,涉及到set的应用,很有意义,打印出所有可能的序列。
https://blog.csdn.net/qq_37360631/article/details/81749691
(16)DFS+bitset,设计到bitset的用法,每次可以翻转一行或者一列,问向上的个数最多是多少个。
https://blog.csdn.net/qq_37360631/article/details/81771564
(17)BFS,给定一个无序树,问能否输出给定的顺序。即问能否用给定顺序BFS进行遍历。
https://blog.csdn.net/qq_37360631/article/details/82388153
3.dfs经典代码举例
/* Poj2386
dfs八联通块
*/
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define For(a,b) for(int a=0;a<b;a++)
#define mem(x) memset(x,0,sizeof(x))
#define sf scanf
#define pf printf
#define maxn 310
int gcd(int a,int b){ return b>0?gcd(b,a%b):a;}
typedef long long ll;
using namespace std;
int n,m,res,ans=0; //n行m列
char mp[maxn][maxn];
int dir[8][2]={-1,0,1,0,0,1,0,-1,-1,-1,-1,1,1,-1,1,1};
void dfs(int x,int y){
mp[x][y]='.'; //这个地方标记为已经访问
for(int i=0;i<8;i++){
int dx=x+dir[i][0];
int dy=y+dir[i][1];
//判断是否在院子内,是否有积水
if(dx>=0&&dx<n&&dy>=0&&dy<m&&mp[dx][dy]=='W')
dfs(dx,dy);
}
}
int main(){
ans=0;
cin>>n>>m;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
// sf("%c",&mp[i][j]); 用sf后面需要加上getchar()把回车读了
cin>>mp[i][j];
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(mp[i][j]=='W'){
dfs(i,j);
ans++;
}
}
}
cout<<ans<<endl;
return 0;
}
bfs经典代码,迷宫最短路径
/* n*m的矩阵,从左上角走到右下角最少多少步
#表示墙壁,.表示通行
3 3
.#.
.##
...
*/
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define For(a,b) for(int a=0;a<b;a++)
#define mem(x) memset(x,0,sizeof(x))
#define Debug(x) cout<<"---> "<<x<<endl;
#define sf scanf
#define pf printf
#define maxn 310
int gcd(int a,int b){ return b>0?gcd(b,a%b):a;}
typedef long long ll;
typedef pair<int,int> P;
//head
int n,m,res=0,ans=0; //n行m列
char mp[maxn][maxn];
int d[maxn][maxn];
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
//求解从(x1,y1)到(x2,y2)的最短距离
int bfs(int x1,int y1,int x2,int y2){
queue<P> que;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++) d[i][j]=inf;
//将起点放队列,并把这个点的距离标记为0
que.push(P(x1,y1));
d[x1][y1]=0;
//不断循环知道队列的长度为0
while(que.size()){
P p=que.front(); que.pop();
if(p.first==x2 &&p.second==y2) break;
for(int i=0;i<4;i++){
int nx=p.first+dx[i];
int ny=p.second+dy[i];
//判断是否可以移动以及是否访问过,距离为Inf就是没访问过
if(d[nx][ny]==inf &&mp[nx][ny]!='#'&&nx>=0&&nx<n&&ny>=0&&ny<m) {
que.push(P(nx,ny));
d[nx][ny]=d[p.first][p.second]+1;
}
}
}
return d[x2][y2];
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>mp[i][j];
}
}
int res=bfs(0,0,n-1,m-1);
cout<<res<<endl;
return 0;
}