深度优先搜索

:::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。

0123456
1000000
2001111
3011001
4110001
5100001
6111111

image.png

#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

12345
1..###
2#....
3#.#.#
4#.#.#
5#.#..

image.png

#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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值