以题为例浅谈DFS算法

DFS算法是什么

深度优先搜索算法(Depth First Search 简称DFS算法),一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。

在数据结构中它是属于图的一种遍历算法,从名字我们也可以看出它的遍历方法就是它从一个点开始一直往下遍历直到遍历到空在退回来接着下一个遍历;例如:

我们用DFS算法去遍历这个图;

从1开始,先遍历2(这里并没有什么要求,也可以先遍历3,但最好是按照顺序去遍历),2遍历之后就开始遍历5,5遍历完之后开始遍历9,9遍历完之后,在往下遍历就是空了,所以就开始往后退,退到5看看5的所有结点遍历完没有,在这里是遍历完了,在往后退到2,看看2左右结点遍历完没有如果遍历完了在退到1,看看1结点遍历完没有,在这里是没有遍历完的就开始去遍历3以此类推

所以它的遍历结果为:

1 2 5 9 3 6 10 7 4 8

这就是深度优先算法

DFS算法模板

c语言模板

int a[510];   //存储每次选出来的数据
int b[510];   //标记是否被访问
int count = 0; //记录符合条件的次数void DFS(int l){if(l == k){ //k个数已经选完,可以进行输出等相关操作 for(int i = 0; i < l; i++){printf("%d ", a[i]);} count++;return ;}for(int i = 0; i < n; i++){ //遍历 n个数,并从中选择k个数 if(!b[i]){ //若没有被访问 b[i] = 1; //标记已被访问 a[l] = i;  //选定本数,并加入数组 DFS(l + 1);  //递归,l+1 b[i] = 0;  //释放,标记为没被访问,方便下次引用 }}
}

我感觉c++的模板可以用类c进行写,我看到一位大佬的博客用的是vector容器

大佬的博客为:DFS (深度优先搜索) 算法详解 + 模板 + 例题,这一篇就够了_dfs算法-CSDN博客

c++模板

vector<int> a; // 记录每次排列 
vector<int> book; //标记是否被访问 void DFS(int cur, int k, vector<int>& nums){if(cur == k){ //k个数已经选完,可以进行输出等相关操作 for(int i = 0; i < cur; i++){printf("%d ", a[i]);} return ;}for(int i = 0; i < k; i++){ //遍历 n个数,并从中选择k个数 if(book[nums[i]] == 0){ //若没有被访问a.push_back(nums[i]); //选定本输,并加入数组 book[nums[i]] = 1; //标记已被访问 DFS(cur + 1, n, nums); //递归,cur+1 book[nums[i]] = 0; //释放,标记为没被访问,方便下次引用 a.pop_back(); //弹出刚刚标记为未访问的数}}
}

题例

多说无益以题见真章

P8707 [蓝桥杯 2020 省 AB1] 走方格

题目

题目描述:

在平面上有一些二维的点阵。

这些点的编号就像二维数组的编号一样,从上到下依次为第 11 至第 nn 行,从左到右依次为第 11 至第 mm 列,每一个点可以用行号和列号来表示。

现在有个人站在第 11 行第 11 列,要走到第 nn 行第 mm 列。只能向右或者向下走。

注意,如果行号和列数都是偶数,不能走入这一格中。

问有多少种方案。

输入格式:

输入一行包含两个整数 nn,mm。

输出格式:

输出一个整数,表示答案。

输入样例

3 4

输出样例

2

题目地址:[蓝桥杯 2020 省 AB1] 走方格 - 洛谷

这道题感觉就是走迷宫的简便版

先附上代码

#include <bits/extc++.h>
#define int long longusing namespace std;int n,m;int dfs(int x,int y){if(x>n||y>m) //如果越界了,那么就不算.return 0; if(x==n&&y==m) 走到第 n 行第 m 列时,证明我们已经走到了终点,所以增加 1 .return 1;if((x%2==0)&&(y%2==0)) //如果走到了题目中规定不走的格子,那么也不算.return 0; //注意if的顺序不能错哟int ans=dfs(x+1,y)+dfs(x,y+1); //递归求解return ans; //返回答案
}signed main(){cin>>n>>m;cout<<dfs(1,1);
}

这个你提交上去它会提示你最后一步超时了,这是为什么呢?这就是递归的弊端了;

在这里它每次都会有两次选择要么向下走,要么向右走,这里不用考虑向上,向左走,因为你已经在左上端了,向右和向下就可以到达目的地了,所以当n和m的值特别大,时间复杂度就是指数级别的

接下来就是第二种方法,进行记录,先上代码

#include <bits/stdc++.h>using namespace std;int n,m;
int mem[100][100]; //记忆化int dfs(int x,int y){if(x>n||y>m)return 0;if(x==n&&y==m)return 1;if((x%2==0)&&(y%2==0))return 0;if(mem[x][y]!=-1)return mem[x][y];int ans=dfs(x+1,y)+dfs(x,y+1);return mem[x][y]=ans;
}signed main(){memset(mem,-1,sizeof(mem)); //记得清空为-1cin>>n>>m;cout<<dfs(1,1);
}

这次多加了一个数组进行记录如果遍历到就将这个数记录下来,下一次如果遇到相同的直接返回值就行;这次时间复杂度就为O(m*n)每走一步就记录下来那么每个函数就只访问一次

交上去是正确的

P8662 [蓝桥杯 2018 省 AB] 全球变暖

题目

题目描述:

# [蓝桥杯 2018 省 AB] 全球变暖

## 题目描述

你有一张某海域 $N \times N$ 像素的照片,`.` 表示海洋、 `#` 表示陆地,如下所示:

```
.......
.##....
.##....
....##.
..####.
...###.
.......
```

其中 "上下左右" 四个方向上连在一起的一片陆地组成一座岛屿。例如上图就有 $2$ 座岛屿。

由于全球变暖导致了海面上升,科学家预测未来几十年,岛屿边缘一个像素的范围会被海水淹没。具体来说如果一块陆地像素与海洋相邻(上下左右四个相邻像素中有海洋),它就会被淹没。

例如上图中的海域未来会变成如下样子:

```
.......
.......
.......
.......
....#..
.......
.......
```

请你计算:依照科学家的预测,照片中有多少岛屿会被完全淹没。

## 输入格式

第一行包含一个整数 $N$。$(1 \le N \le 1000)$。

以下 $N$ 行 $N$ 列代表一张海域照片。

照片保证第 $1$ 行、第 $1$ 列、第 $N$ 行、第 $N$ 列的像素都是海洋。

## 输出格式

一个整数表示答案。

## 样例 #1

### 样例输入 #1

```
7
.......
.##....
.##....
....##.
..####.
...###.
.......
```

### 样例输出 #1

```
1
```

## 提示

时限 1 秒, 256M。蓝桥杯 2018 年第九届省赛

题目链接:[蓝桥杯 2018 省 AB] 全球变暖 - 洛谷

先上代码

#include<bits/stdc++.h>
using namespace std;
int n,cnt,sum,ans,t,dx[]={0,1,0,-1},dy[]={1,0,-1,0};  //dx,dy表示四个方向
char mp[1010][1010];
void dfs(int x,int y)
{if(!t){cnt=0;for(int i=0;i<4;i++){if(mp[x+dx[i]][y+dy[i]]!='.'){cnt++;}}   //记录它四个方向是不是陆地if(cnt==4)ans++,t=1;  //如果四个方向都是陆地那么它就不会被淹没}mp[x][y]='*';for(int i=0;i<4;i++){int xx=x+dx[i],yy=y+dy[i]; if(xx<0||xx>=n||yy<0||yy>=n||mp[xx][yy]!='#')continue;dfs(xx,yy);}	//这个是检查它的越界问题并且进行递归
}
int main()
{cin>>n;for(int i=0;i<n;i++){for(int j=0;j<n;j++){cin>>mp[i][j];}} for(int i=1;i<n-1;i++){for(int j=1;j<n-1;j++){if(mp[i][j]=='#'){sum++;t=0;dfs(i,j);}}}cout<<sum-ans;
}

解释一下这段代码的大概含义,就是设置一个主函数并且用t进行记录,从而不让他重复记录小岛,如果t=0说明这个陆地还没有被记录,如果t=1说明这个小岛已经被记录了,它的上下左右的一个陆地已经被记录代表这个小岛了,直到将这个小岛的全部陆地全部记录完在进行返回主函数进行下一次的循环;

在学这个算法时候发现自己的递归没有学好,一些小的细节没有搞懂,之后在思考思考,之后会在发文章进行补充;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/542887.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php彩虹/异世界云商全解系统

系统更新与修复列表 1. 基于彩虹的二次开发 - 对彩虹系统进行了二次开发&#xff0c;增强了系统的功能和性能。2. 新增自定义输入框提示内容&#xff08;支持批量修改&#xff09; - 用户可以自定义输入框的提示内容&#xff0c;并支持批量修改&#xff0c;提升用户体验。3. 新…

Spring Boot+Vue前后端分离项目如何部署到服务器

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

IO流(1)——文件输入输出流(FIleInputStream、FIleOutputStream)

IO流概述 IO流应用场景 FileInputStream&#xff08;文件字节输入流&#xff09; 方法 使用read&#xff08;&#xff09;每次读取一个字节的弊端 使用read&#xff08;byte[] buffer&#xff09;方法每次读取多个字节&#xff0c;取多少&#xff0c;倒多少 解决方法 文件字节…

C++ 开发篇+一个简单的数据库管理系统ZDB

说明&#xff1a;本文供数据库爱好者和初级开发人员学习使用 标签&#xff1a;数据库管理系统、RDBMS、小程序、C、C程序 系统&#xff1a;Windows 11 x86 CPU &#xff1a;Intel IDE &#xff1a;Visual Studio 2022 语言&#xff1a;C语言 标准&#xff1a;C14 提示&#xff…

在idea中配置tomcat服务器,部署一个项目(下载教程加链接)

第一步&#xff1a;把Tomcat下载好 ww​​​​​​​Apache Tomcat - Welcome! 链接如上&#xff1a;进去后在左边找到Tomcat8点击进去后 找到图下内容 第二步&#xff1a; 打开这个文件点击bin进去 会出现一个黑色框框&#xff0c;也就是服务器 完成后就可以在浏览器输入…

掘根宝典之C++普通迭代器和反向迭代器详解

简介 迭代器是一种用于遍历容器元素的对象。它提供了一种统一的访问方式&#xff0c;使程序员可以对容器中的元素进行逐个访问和操作&#xff0c;而不需要了解容器的内部实现细节。 C标准库里每个容器都定义了迭代器&#xff0c;这迭代器的名字就叫容器迭代器 迭代器的作用类…

Yolo系列算法-理论部分-YOLOv1

0. 紧接上一篇目标检测算法的介绍 基于深度学习的目标检测算法概述-CSDN博客 本篇YOLO算法系列&#xff0c;参考优秀作者-AI菌&#xff0c;文章链接&#xff1a;YOLO系列算法精讲&#xff1a;从yolov1至yolov8的进阶之路&#xff08;2万字超全整理&#xff09;_yolov9-CSDN博…

deepin23beta中SQLite3数据库安装与使用

SQLite 是一个嵌入式 SQL 数据库引擎&#xff0c;它实现了一个自包含、无服务器、零配置、事务性 SQL 数据库引擎。 SQLite 的代码属于公共领域&#xff0c;因此可以免费用于任何商业或私人目的。 SQLite 是世界上部署最广泛的数据库&#xff0c;其应用程序数量之多&#xff0c…

HarmonyOS应用开发-Stage模型开发概述

基本概念 UI框架 HarmonyOS提供了一套UI开发框架&#xff0c;即方舟开发框架&#xff08;ArkUI框架&#xff09;。提供了应用UI开发所必需的能力&#xff1a;多种组件、布局计算、动画能力、UI交互、绘制。 方舟开发框架针对开发者提供了两种开发范式&#xff1a; 基于ArkTS…

STM32-位带操作及位带别名区

这里写自定义目录标题 一、位带操作的基本含义及作用二、以STM32为例三、位带别名区和位带区(寄存器地址位地址)的转换关系四、使用例程 一、位带操作的基本含义及作用 位带别名区的设计主要是为了**方便对位带区单个比特位进行读写操作**。在某些应用场景下&#xff0c;需要频…

Hive借助java反射解决User-agent编码乱码问题

一、需求背景 在截取到浏览器user-agent&#xff0c;并想保存入数据库中&#xff0c;经查询发现展示的为编码后的结果。 现需要经过url解码过程&#xff0c;将解码后的结果保存进数据库&#xff0c;那么有几种实现方式。 二、问题解决 1、百度&#xff1a;url在线解码工具 …

Java 与 Go:可变数组

可变数组&#xff08;也称为动态数组&#xff09;是一种可以在运行时动态增加或减少其大小的数据结构。由于其动态分配大小&#xff0c;灵活性增删改查&#xff0c;动态地管理内存&#xff08;在需要时动态分配内存空间&#xff0c;以适应数据结构的大小变化&#xff0c;而不会…