深度优先搜索算法(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;
}