:::info
深度优先搜索(Depth-First Search,DFS)是一种用于图遍历或树遍历的算法。它从起点开始沿着一条路径一直走到底,直到无法再继续前进,然后返回上一个节点继续搜索,直到所有节点都被访问过为止。
具体实现时,可以用递归或栈的方式来实现深度优先搜索。在递归实现中,从起点开始递归搜索下一个节点,如果遇到无法继续前进的情况,就返回上一个节点继续搜索;在栈的实现中,每次将当前节点的所有邻居节点压入栈中,然后取出栈顶元素,重复这个过程直到栈为空。
深度优先搜索可以用于找到图或树的某个节点,或者找到图或树中的一条路径。但是需要注意的是,由于深度优先搜索是一种盲目搜索算法,所以在处理大型图或树时可能会出现性能问题,并且不一定能够找到最优解。
填涂颜色(作业问题)
描述
由数字0组成的方阵中,有一任意形状闭合圈,闭合圈由数字1构成,围圈时只走上下左右4个方向。现要求把闭合圈内的所有空间都填写成2。例如:6×6的方阵(n=6),涂色前和涂色后的方阵如下:
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1
输入
每组测试数据第一行一个整数n(1≤n≤30)。
接下来n行,由0和1组成的n×n的方阵。
方阵内只有一个闭合圈,圈内至少有一个0。
输出
已经填好数字2的完整方阵。
6
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1
输入样例 1
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1
输出样例 1
提示
对于100%的数据,1≤n≤30。
0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 1 | 1 | 1 | 1 |
3 | 0 | 1 | 1 | 0 | 0 | 1 |
4 | 1 | 1 | 0 | 0 | 0 | 1 |
5 | 1 | 0 | 0 | 0 | 0 | 1 |
6 | 1 | 1 | 1 | 1 | 1 | 1 |
#include <bits/stdc++.h>
using namespace std;
char maze[40][40];//存放方阵信息
int n;//表示方阵的大小n*n
int fx[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};//方向
void dfs(int x, int y) {
maze[x][y] = '3';//将0换成3
for (int i = 0; i < 4; i++) {//遍历4方向
int nx = x + fx[i][0], ny = y + fx[i][1];
if (nx >= 1 && nx <= n && ny >= 1 && ny <= n && maze[nx][ny] == '0') {//判断该位置是否在方阵内且是否为0
dfs(nx, ny);
}
}
}
int main() {
cin >> n;//输入n
for (int i = 1; i <= n; i++) {//输入方阵信息
for (int j = 1; j <= n; j++) {
cin >> maze[i][j];
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {//遍历方阵信息
if ((i == 1 || i == n || j == 1 || j == n) && maze[i][j] == '0') {//如果边界的0
dfs(i, j);//深搜
}
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (maze[i][j] == '3') {//若为3,表示为边缘的0
cout << '0' << " ";
} else if (maze[i][j] == '0') {//中间的0
cout << '2' << " ";
} else {
cout << maze[i][j] << " ";//剩下的1
}
}
cout << endl;
}
}
走出迷宫的最少步数
描述
一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走;有的格子是空地,可以走。
给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)。只能在水平方向或垂直方向走,不能斜着走。
输入
第一行是两个整数,R和C,代表迷宫的行数和列数。(1≤R,C≤40)
接下来是R行,每行C个字符,代表整个迷宫。空地格子用’.‘表示,有障碍物的格子用’#‘表示。
迷宫左上角和右下角都是’.'。
输出
输出从左上角走到右下角至少要经过多少步(即至少要经过多少个空地格子)。
计算步数要包括起点和终点。
输入样例 1
5 5
…###
#…
#.#.#
#.#.#
#.#…
输出样例 1
9
1 | 2 | 3 | 4 | 5 | |
---|---|---|---|---|---|
1 | . | . | # | # | # |
2 | # | . | . | . | . |
3 | # | . | # | . | # |
4 | # | . | # | . | # |
5 | # | . | # | . | . |
#include <bits/stdc++.h>
using namespace std;
char maze[45][45];//存放方阵信息
int bs[45][45];//存放迷宫从起点到该位置上的最小步数
int n,m;//表示方阵的大小n*m
int fx[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};//方向
void dfs(int x, int y,int s) {
bs[x][y]=s;
for(int i=0;i<4;i++){//遍历四个方向
int nx=x+fx[i][0],ny=y+fx[i][1];
if(maze[nx][ny]=='.'&&bs[nx][ny]>s+1){//判断该位置值是否比下一步数少
dfs(nx,ny,s+1);
}
}
}
int main() {
cin >> n>>m;//输入n
for(int i=1;i<=n;i++){//输入迷宫信息
for(int j=1;j<=m;j++){
cin>>maze[i][j];
bs[i][j]=INT_MAX;//int的最大值
}
}
dfs(1,1,1);
cout<<bs[n][m];
return 0;
}
小 X 学游泳(swim)
描述
暑假快到啦,小 X 准备趁着这个暑假去学游泳。可是一开始小 X 就遇到了一个难题。
游泳池划分成了一个n×m的方格, 这里n×m表示n行m列。 因 为游泳池里的水深浅不一,所以这n×m个方格对于小 X 的危险系数也会不一样。
而小 X 目前需要从左上角 的方格(1,1)出发, 游到右下角 的方格(n,m),小 X 每次只 能从当前方格游到上下左右四个相邻的方格中的某一格,并且在到达终点前不能离开游泳池。
小 X 很担心会发生什么危险,所以希望你能帮他找一条危险系数最小的路径。
一条路径的危险系数定义为这条路径所经过的方格的危险系数之和。
注意:这条路径不能经过同一个方格两次(小 X 当然不希望去那么危险的地方再游一次)
输入
输入数据第一行有两个用空格隔开的正整数n和m, 表示泳池的行数和列数。
接下来共有n行数据,每行有m个用空格隔开的大于等于0的整数, 表示每个方格的危险系数
输出
输出仅有一行包含一个整数ans, 表示要求的从左上角的方格(1,1)出发, 游到右下角的方格(n,m)的最小的危险系数。
输入样例 1
4 5
1 7 2 8 2
3 10 1 5 1
2 8 3 7 1
1 2 1 20 1
输出样例 1
19
提示
对于30%的数据,1≤n,m≤5
对于另外40%的数据,1≤n,m≤20, 每个方格的危险系数 =0或1
对于100%的数据,1≤n,m≤30,0≤每个方格的危险系数≤100000
【样例解释】
路径:(1,1)→(1,2)→(1,3)→(2,3)→(2,4)→(2,5)→(3,5)→(4,5), 危险系数之和为1+7+2+1+5+1+1+1=19。
#include <bits/stdc++.h>
using namespace std;
int maze[45][45];//存放方阵信息
int bs[45][45];//存放从起点到达该位置的最小危险系数
int n,m;//表示方阵的大小n*m
int fx[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};//方向
void dfs(int x, int y,int s) {
bs[x][y]=s;
for(int i=0;i<4;i++){//遍历四个方向
int nx=x+fx[i][0],ny=y+fx[i][1];
if(bs[nx][ny]>s+maze[nx][ny]&&bs[nx][ny]!=0){//判断该位置值是否比下一步危险系数少
dfs(nx,ny,s+maze[nx][ny]);//返回每一次所增加的值
}
}
}
int main() {
cin >> n>>m;//输入n,m,表示方格的行列
for(int i=1;i<=n;i++){//输入方阵信息
for(int j=1;j<=m;j++){
cin>>maze[i][j];
bs[i][j]=INT_MAX;//int的最大值 将每一个格子的危险系数初始化为最大
}
}
dfs(1,1,maze[1][1]);
cout<<bs[n][m];
return 0;
}
走出迷宫的最少步数2
描述
当你站在一个迷宫里的时候,往往会被错综复杂的道路弄得失去方向感,如果你能得到迷宫地图,事情就会变得非常简单。假设你已经得到了一个n×m的迷宫的图纸,请你找出从起点到出口的最短路。
输入
第一行是两个整数n和m(1≤n,m≤100),表示迷宫的行数和列数。
接下来n行,每行一个长为m的字符串,表示整个迷宫的布局。字符’.‘表示空地,’#'表示墙,'S’表示起点’T’表示出口。
输出
输出从起点到出口最少需要走的步数。
输入样例 1
3 3
S#T
.#.
…
输出样例 1
6
#include <bits/stdc++.h>
using namespace std;
char maze[110][110];//存放方阵信息
int bs[110][110];//存放迷宫从起点到该位置上的最小步数
int n,m,endx,endy,startx,starty;//表示方阵的大小n*m
int fx[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};//方向
void dfs(int x, int y,int s) {
bs[x][y]=s;
for(int i=0;i<4;i++){//遍历四个方向
int nx=x+fx[i][0],ny=y+fx[i][1];
if(maze[nx][ny]=='.'&&bs[nx][ny]>s+1){//判断该位置值是否比下一步数少
dfs(nx,ny,s+1);
}
}
}
int main() {
cin >> n>>m;//输入n ,m
for(int i=1;i<=n;i++){//输入迷宫信息
for(int j=1;j<=m;j++){
cin>>maze[i][j];
bs[i][j]=INT_MAX;//int的最大值
if(maze[i][j]=='T'){//记录终点坐标
endx=i,endy=j;
maze[i][j]='.';
}
if(maze[i][j]=='S'){//记录起点坐标
startx=i,starty=j;
}
}
}
dfs(startx,starty,0);
cout<<bs[endx][endy];
return 0;
}