深度优先搜索算法(Depth First Search,简称DFS):一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。
主要思想:不撞南墙不回头,一条路走到黑
算法思想
回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
而回溯法大概率将会用到递归,例如无论是树还是图的遍历,采用dfs遍历时,都会用到递归
dfs递归算法基本框架
/*
该DFS 框架以2D 坐标范围为例,来体现DFS 算法的实现思想。
*/
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
const int maxn=100;
bool vst[maxn][maxn]; // 访问标记
int map[maxn][maxn]; // 坐标范围
int dir[4][2]={0,1,0,-1,1,0,-1,0}; // 方向向量,(x,y)周围的四个方向
bool CheckEdge(int x,int y) // 边界条件和约束条件的判断
{
if(!vst[x][y] && ...) // 满足条件
return 1;
else // 与约束条件冲突
return 0;
}
void dfs(int x,int y)
{
vst[x][y]=1; // 标记该节点被访问过
if(map[x][y]==G) // 出现目标态G
{
...... // 做相应处理
return;
}
for(int i=0;i<4;i++)
{
if(CheckEdge(x+dir[i][0],y+dir[i][1])) // 按照规则生成下一个节点
dfs(x+dir[i][0],y+dir[i][1]);
}
return; // 没有下层搜索节点,回溯
}
int main()
{
......
return 0;
}
例题:2018蓝桥杯c/c++大学生B组 :全球变暖
题目描述
你有一张某海域 NxN 像素的照片,"."表示海洋、"#"表示陆地,如下所示:
.......
.##....
.##....
....##.
..####.
...###.
.......
其中"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有 2 座岛屿。
由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。
例如上图中的海域未来会变成如下样子:
.......
.......
.......
.......
....#..
.......
.......
请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。
输入描述
第一行包含一个整数 N(1≤N≤1000)。
以下 N 行 N 列代表一张海域照片。
照片保证第 1 行、第 1 列、第 N 行、第 N 列的像素都是海洋。、
输出一个整数表示答案。
输入输出样例
示例
输入
7
.......
.##....
.##....
....##.
..####.
...###.
.......
输出
1
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define MAX 1000+10
int dx[4]={0,0,-1,1},dy[4]={1,-1,0,0};
char mp[MAX][MAX];
int st[MAX][MAX];
int n;
bool legal(int a,int b){ //判断边界是否合法
return a>=1&&a<=n&&b>=1&&b<=n;
}
bool dfs(int a,int b){ //深度优先搜索函数
st[a][b]=1;
int cnt=0;
bool flag=false;
for(int i=0;i<4;i++){
int nx=a+dx[i],ny=b+dy[i];
if(legal(nx,ny)&&mp[nx][ny]=='#'){
cnt++;
if(st[nx][ny]==0){
flag=dfs(nx,ny)||flag; //只要有一层递归返回值为true,
true值就会一直被传递给最上一层的flag并返回
}
}
}
return cnt==4||flag;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);//无关紧要的,单纯为了提升cin和cout速度
memset(st,0,sizeof(st));
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>mp[i][j];
}
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(mp[i][j]=='#'&&st[i][j]==0&&!dfs(i,j))
ans++;
}
}
cout<<ans;
return 0;
}