【深度优先搜索DFS】

文章目录

  • 概念
  • 模版:迷宫游戏
  • 模版:迷宫最短路径问题
  • 例题-迷宫类
  • 例题-连通块类
  • 例题-其他类

概念

深度优先搜索按照深度优先的方式进行搜索,通俗地说就是“一条路走到黑”。注意,这里的搜索指的是一种穷举的方式,把所有可行的方案都列出来,不断去尝试,直到找到问题的解。

深度优先搜索和递归的区别是:深度优先搜索是一种算法,注重的是思想;而递归是一种基于编程语言的实现方式,也就是说递归是实现深度优先搜索的这个算法的手段。

模版:迷宫游戏

【深度优先搜索DFS】_第1张图片
迷宫问题的解法就需要dfs。我们对上下左右四个方向,一个方向一个方向地尝试,如果沿着某个方向不能走到终点,我们就要原路返回,继续尝试其他方向,直到走出迷宫。

上面这种走法,就对应着我们的dfs算法。首先找到起点S,走到每个点时,按照左下右上四个方向尝试。每走到下一个点以后,我们就把这个点当作起点S,继续按顺序尝试。

如果某个点四个方向都尝试过但是走不通的话,我们就往回走一个点,这一步我们称之为回溯,继续尝试上一个点的其他方向,直到所有点都尝试个四个方向。

迷宫模板

伪代码

bool bfs(int x, int y){
	if(x,y)是终点{
		//找到了路径
		return true;
	}
	标记(x,y)已被访问
	向上走到位置(tx,ty)
	if(tx,ty)在地图里且没有被访问{
		if(dfs(tx,ty)==true){
			return true;
		}
	}
	向左走到位置(tx,ty)
	if(tx,ty)在地图里且没有被访问{
		if(dfs(tx,ty)==true){
			return true;
		}
	}
	向下走到位置(tx,ty)
	if(tx,ty)在地图里且没有被访问{
		if(dfs(tx,ty)==true){
			return true;
		}
	}
	向右走到位置(tx,ty)
	if(tx,ty)在地图里且没有被访问{
		if(dfs(tx,ty)==true){
			return true;
		}
	}
	如果都不行则取消(x,y)的标记
	return false;
}
	

代码实现

#include 
using namespace std;
int n,m,x,y;
char maze[105][105];
bool vis[105][105];
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
bool in(int x,int y){
    return x<n&&x>=0&&y<m&&y>=0;
}
bool dfs(int x,int y){
    if(maze[x][y]=='T'){
        return true;
    }
    vis[x][y]=1;
    maze[x][y]='m';
    for(int i=0;i<4;i++){
        int tx=x+dir[i][0];
        int ty=y+dir[i][1];
        if(in(tx,ty)&&maze[tx][ty]!='*'&&!vis[tx][ty]){
            if(dfs(tx,ty)){
                return true;
            }
        }
    }
    vis[x][y]=0;
    maze[x][y]='.';
    return false;
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cin>>maze[i][j];
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(maze[i][j]=='S'){
                x=i;
                y=j;
            }
        }
    }
    if(dfs(x,y)){
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                cout<<maze[i][j];
            }
            cout<<endl;
        }
    }else{
        cout<<"NO"<<endl;
    }
} // namespace std;

模版:迷宫最短路径问题

#include 
using namespace std;
int n,m,x,y;
int ans=1000000;
char maze[100][100];
bool vis[100][100];
int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
bool in(int x,int y){
    return x>=0&&x<n&&y>=0&&y<m;
}
void dfs(int x,int y,int step){
    if(maze[x][y]=='T'){
        if(step<ans){
            ans=step;
        }
        return;
    }
    vis[x][y]=1;
    for(int i=0;i<4;i++){
        int tx=x+dir[i][0];
        int ty=y+dir[i][1];
        if(in(tx,ty)&&maze[tx][ty]!='*'&&!vis[tx][ty]){
            dfs(tx,ty,step+1);
        }
    }
    vis[x][y]=0;

}
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cin>>maze[i][j];
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(maze[i][j]=='S'){
                x=i;
                y=j;
            }
        }
    }
    dfs(x,y,0);
    cout<<ans<<endl;
} // namespace std;

例题-迷宫类

1.迷宫解的方案数

例题-连通块类

1.踏青 求连通块数
2.最大 求最大连通块数

例题-其他类

1.家谱

你可能感兴趣的:(蓝桥杯,蓝桥杯,c++,算法)