1深度优先搜索介绍
1.1解释:
深度优先搜索(DFS)是一种用于遍历或搜索图和树的算法。它从起始节点开始,沿着路径尽可能深地探索,直到达到目标节点或无法继续为止,然后回溯到最近的一个未探索节点,继续探索。
1.2基本步骤:
-
选择起始节点: 选择起始节点作为开始探索的点。
-
标记节点: 将起始节点标记为已访问,以防止重复访问。
-
探索邻居节点: 从当前节点开始,选择一个相邻的节点进行探索。如果相邻节点未被访问,标记它并将其添加到待访问的节点列表中。
-
深入探索: 重复步骤3,深入到尽可能深的层次,直到达到目标节点或无法再继续为止。
-
回溯: 当无法继续深入时,回溯到上一个未完全探索的节点,并选择另一个相邻节点进行探索。
-
重复: 重复步骤3至步骤5,直到遍历完整个图或找到目标节点。
1.3适用场景:
深度优先搜索不一定找到最短路径,因为它会优先沿着一个路径深入。在实际应用中,深度优先搜索通常用于解决路径搜索问题(寻找可行解)。
2代码实现
由于深度搜索是个递归过程,所以可以用递归函数来实现
void dfs(int dep,其他参数表) //dep是搜索深度
自定义参数;
if(当前目标状态)
{
输出解或者计数
}
else
{
for(int i = 1; i <= 状态扩展的可能性;i++)
{
if(第i种状态扩展可能性)
{
维护自定义参数;
dfs(dep+1,其他参数表)
}
}
}
3过程图解
假设我们要实现下图路径的搜索(搜索可行路径而不是最佳路径):我们可以先新建一个栈结构
规定:
从①开始搜索,先将①标记为已遍历,并对①做入栈操作:
找出与节点①相邻且未被遍历过的节点:有②和⑥两个节点,假设我们设定的顺序规则是先将节点序号小的优先入栈,所以这里将②标记为已遍历,并对②做入栈操作:
找出与节点②相邻且未被遍历过的节点:有③和⑤两个节点,这里将③标记为已遍历,并对③做入栈操作:
找出与节点③相邻且未被遍历过的节点:只有节点④,所以将④标记为已遍历,并对④做入栈操作:
找出与节点④相邻且未被遍历过的节点:只有节点⑤,所以将⑤标记为已遍历,并对⑤做入栈操作:
... ...
此时,节点⑧已经没有与其相邻且未被遍历过的节点了,于是我们开始出栈操作:
弹出栈点中的⑧,栈顶移动到⑦,检查是否有与节点⑦相邻且未被遍历过的节点:
节点⑦没有与其相邻且未被遍历过的节点,继续出栈操作:
弹出栈点中的⑦,栈顶移动到⑥,检查是否有与节点⑥相邻且未被遍历过的节点:
... ...
现在,栈已经为空,整个深度优先搜索也就完成了。
4程序实例
4.1题目描述:
打死我也不说!
梗:最好的密电码是啥? 是“打死我也不说!”这样,即使帮我们传送密电码的猪队友被敌人抓住严刑拷打,我们也不用担心泄露秘密。
现在稍微改进一下,我们把“打死我也不说”的拼音首字母“DSWYBS”藏在一个矩阵里,而代表“打”的字母
D
和代表“说”的字母S
所在的行列下标之和即是密码。对于给定的矩阵,请判断其中是否藏有“DSWYBS”,如果有,给出首末两个字母的下标并计算密码;如果没有,打印一行“DSWYBS”。
注意:
- 若藏有“DSWYBS”,则这串字母必是沿行、列或斜45度方向依次排列的。
- 题目保证输入的矩阵至多藏有一串“DSWYBS”。
- 矩阵左上角下标为(0,0)。
- 区分大小写。
- 题目保证输入的矩阵不含有类似这样的排列(即:仅有DSWYB五个字母,但是字母B与S相邻,可组成DSWYBS的排列 ) :
DSB WY
输入格式:
第一行给出两个整数
M
、N
(均不大于15、不小于4),接下来M行,每行有N个字母或数字,以换行结束。输出格式:
如果输入矩阵中藏有“DSWYBS”,则输出三行,第一行和第二行分别是首字母
D
的下标和末字母S
的下标,先行下标
后列下标
,以一个空格间隔。第三行给出两个字母四项下标值之和。如果没藏有该串字母,则打印一行“DSWYBS”
输入样例1:
8 10 0x00z000d0 00aD00s000 00b0SWk000 000wcY000s 00000B0000 0000S00000 0000000000 0000000000
输出样例1:
1 3 5 4 13
输入样例2:
5 5 12345 adswa 54321 dswys aaaaa
输出样例2:
DSWYBS
4.2代码实现:
#include <stdio.h>
#define MAX_ROWS 20
#define MAX_COLS 20
#define TARGET_CHAR 'D'
#define CHAR_COUNT 7
int n, m, flag = 0;
int x1, y1, x2, y2;
char targetChars[CHAR_COUNT] = {'1', 'D', 'S', 'W', 'Y', 'B', 'S'};
char matrix[MAX_ROWS][MAX_COLS];
void dfs(int x, int y, int step);
int main() {
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i++) {
scanf("%s", &matrix[i]);
}
for (int i = 0; i < n; i++) {
for (int k = 0; k < m; k++) {
if (matrix[i][k] == TARGET_CHAR) {
dfs(i, k, 1);
}
if (flag) {
x1 = i;
y1 = k;
break;
}
}
if (flag) break;
}
if (flag) {
printf("%d %d\n%d %d\n%d", x1, y1, x2, y2, x1 + y1 + x2 + y2);
} else {
printf("DSWYBS");
}
return 0;
}
void dfs(int x, int y, int step) {
int tx, ty;
int next[8][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
if (step == CHAR_COUNT - 1) {
x2 = x;
y2 = y;
flag = 1;
return;
}
for (int i = 0; i < 8; i++) {
tx = x + next[i][0];
ty = y + next[i][1];
if (tx >= 0 && tx < n && ty >= 0 && ty < m && matrix[tx][ty] == targetChars[step + 1]) {
dfs(tx, ty, step + 1);
}
}
}