概念
深度优先搜索(DFS)是一种用于遍历或搜索树或图的结构的算法。它沿着一个路径深入遍历直到末端,然后回溯至最近的分叉点再继续其他路径的遍历,这个过程持续进行直到所有的顶点都被访问过。DFS常常用递归来实现,易于编码,同时也可以手动使用栈来模拟递归过程。在二叉树中,DFS可以用来实现前序、中序、后序遍历。它的应用包括寻找连通分量、拓扑排序以及解决一些组合问题。
1、统计路线-2935
题目描述了一个迷宫探宝问题。迷宫是一个 (N \times N) 的方格,其中“0”表示可以通行的格子,“1”表示不可通行的障碍,“2”表示宝藏的位置。从左上角的位置 (1,1) 开始,要求找到所有能够到达宝藏位置的路径数量。每个格子只能经过一次,且第一个格子不能是“1”。
输入描述:
- 第一行是一个正整数 (N),表示迷宫是 (N \times N) 的方格。
- 接下来的 (N \times N) 行,每行包含由“0”、“1”、“2”组成的序列,分别表示每个格子的状态。
输出描述:
- 输出是一个整数,表示可以找到宝藏的所有不同路径的数量。
样例输入输出解释:
例如,对于一个5x5的迷宫样例:
5
0 0 1 1 0
1 0 0 0 0
0 0 0 0 2
0 1 1 0 0
0 0 0 1 0
一共有12条不同的路径可以从起点到达宝藏。
代码解析:
首先定义了一个迷宫数组 mp
和一个访问标记数组 vis
,以及两个全局变量 ans
(用来计数所有可能的路径)和 n
(表示迷宫的大小)。dx
和 dy
两个数组定义了在迷宫中移动的四个方向(右、下、左、上)。
void dfs(int x,int y){
// ...
}
dfs
函数是深度优先搜索的实现,它尝试从当前位置 (x, y)
探索所有可能的路径。如果当前位置是宝藏,则路径计数加一并返回;否则,它将尝试移动到四个可能的方向上的下一个位置,如果下一个位置在迷宫内、不是障碍并且未被访问过,则进入下一个位置并继续搜索。
主函数 main
读取迷宫的大小和布局,如果起始位置是障碍,则直接输出0;否则,从起始位置开始调用 dfs
函数进行搜索,最终输出找到的宝藏路径总数。
性能考量:
由于迷宫的大小限制在 (10 \times 10) 以内,这个深度优先搜索算法在性能上是可接受的。尽管在最坏情况下,可能的路径数量可能会非常大,但由于路径上的每个格子只能访问一次,所以实际的搜索空间相对较小。
示例输出解释:
对于第二个样例输入:
2
0 0
0 2
输出为2,表示存在两条路径可以到达宝藏。
#include<iostream>
using namespace std;
int mp[10][10]={
};//地图
bool vis[10][10]={
};//记录是否访问过
int dx[4]={
0,1,0,-1},dy[4]={
1,0,-1,0};//右下左上
int ans=0,n;//ans:统计线路 n:n*n的地图
void dfs(int x,int y){
if(mp[x][y]==2){
//找到宝藏
ans++;//累加线路
return ;//返回到上一个方格
}
for(int i=0;i<4;i++){
//遍历四个方向
int nx=x+dx[i];//下一个方格的行下标
int ny=y+dy[i];//下一个方格的列下标
if(nx>0&&nx<=n && ny>0&&ny<=n){
//在地图内
if(mp[nx][ny]!=1 && vis[nx][ny]==0){
//方格不是假山同时没有访问过
vis[nx][ny]=1;//当前方格标记访问过
dfs(nx,ny);//重复上述步骤
vis[nx][ny]=0;//递归返回到当前房间,当前房间标记为0(回溯)
}
}
}
}
int main(){
cin>>n;//地图大小
for(int i=1;i<=n;i++){
//生成地图
for(int j=1;j<=n;j++)
cin>>mp[i][j];
}
if(mp[1][1]==1){
//第一个方格为1,有0条路径
cout<<0;//输出0
return 0;//结束程序
}
vis[1][1]=1;//第一个方格访问过
dfs(1,1);//深搜
cout<<ans;//找到宝藏总线路
return 0;
}
2、八个方向-2936
题目描述了一个通过迷宫寻宝的场景。迷宫由 (N \times N) 个房间组成,每个房间都可以通向周围的八个房间(允许对角线移动)。迷宫中有些房间被蝙蝠占据(用1表示),不能通过;有些房间是空的(用0表示),可以通过;还有一个房间藏有宝藏(用2表示)。起点位于 (1,1),且起点房间没有蝙蝠。需要判断是否存在一条路径可以从起点到达藏有宝藏的房间。
输入描述:
- 第一行是一个正整数 (N) ((2 < N \leq 10)),表示迷宫的大小。
- 接下来是一个 (N \times N) 的矩阵,矩阵中的数值用于表示迷宫房间的状态(0表示空房间,1表示有蝙蝠的房间,2表示有宝藏的房间)。
输出描述:
- 如果可以找到宝藏,则输出 “YES”;如果找不到宝藏,则输出 “NO”。
样例输入输出解释:
例如,对于样例输入1:
6
0 0 1 1 0 0
1 0 0 1 0 0
0 0 0 1 2 0
0 1 1 1 0 0
0 0 0 1 0 0
0 0 0 1 0 0
由于宝藏被蝙蝠包围,没有办法到达宝藏的位置,所以输出 “NO”。
对于样例输入2:
5
0 0 0 0 0
0 0 1 1 1
0 0 0 1 0
0 1 0 1 2
0 0 0 0 1
存在一条路径可以避开蝙蝠,从 (1,1) 到达宝藏的位置,所以输出 “YES”。
代码解析:
定义了一个迷宫数组 mp
和一个访问标记数组 vis
。数组 dx
和 dy
分别存储了从当前房间移动到相邻房间的行和列的变化量(包括对角线移动)。flag
变量用来标记是否找到宝藏。
void dfs(int x, int y){
// ...
}
dfs
函数是深度优先搜索的实现,用于探索迷宫。如果当前位置是宝藏,就设置 flag
为 true
并返回。否则,函数会尝试访问当前位置周围的所有房间,除非房间中有蝙蝠或已经访问过。
在 main
函数中,读取迷宫的大小和布局,然后从起点开始调用 dfs
函数进行搜索。搜索完成后,根据 flag
的值输出结果。
性能考量:
给定的迷宫大小最大为 (10 \times 10),所以深度优先搜索在此问题上是可行的。即便最坏的情况下,可能的路径数量是大的,但由于每个房间只能访问一次,实际的搜索空间是有限的。
示例输出解释:
对于给定的迷宫,程序将执行深度优先搜索,并根据是否可以找到一条通往宝藏的路径来输出 “YES” 或 “NO”。
#include<iostream>
using namespace std;
int mp[11][11],n;
bool vis[11][11];
//上、右上、右、右下、下、左下、左、左上
int dx[8]={
-1,-1,0,1,1,1,0,-1};
int dy[8]={
0,1,1,1,0,-1,-1,-1};
bool flag=false;//flag表示是否找到宝箱,false:未找到
void dfs(int x,int y){
if(mp[x][y]==2){
//找到宝箱
flag=true;//标记找到宝箱
return ;
}
for(int i=0;i<8;i++){
//遍历当前房间的八个方向
int nx=x+dx[i];//下一个房间的行下标
int ny=y+dy[i];//下一个房间的列下标
if(nx>0&&nx<=n && ny>