C++:第十一讲DFS深搜

Everyday English

Your optimal career is simply this: Share the real you with physical world through th e process of creative self-expression.
你的最佳职业很简单,就是这样:通过创造性自我表达的途径和世界分享真实的你。

前言

今天带着大家学习一个既简单又重要的算法——深搜函数DFS。

DFS

一、基本思想

  1. 为了求得问题的解,先选择某一种可能情况向前探索;
  2. 在探索过程中,一旦发现原来的选择是错误的,就退回一步重新选择,继续向前探索;
  3. 如此反复进行,直至得到解或证明无解

二、搜索算法

搜索算法,就是利用计算机的高性能,对问题的“状态空间”进行枚举,穷举出一个问题的全部或者部分可能的情况,找到最优解或者统计合法解的个数。        在搜索算法中,深度优先搜索算法(Depth First Search,DFS,简称深搜),常常指利用递归函数方便地实现暴力枚举的算法,也称为“回溯法”。通过递归函数,我们可以逐层地枚举每一种可能,从而实现枚举所有可能的“状态”。       搜索算法是一些高级算法的基础,而搜索算法可以在很多问题中解决数据范围较小的部分。掌握正确的写搜索算法,对后续高级算法的学习和理解有着一定的帮助。

三、深搜模版(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(); //弹出刚刚标记为未访问的数}}
}

例题(洛谷P1706全排列问题)

题目描述

按照字典序输出自然数 1到 n 所有不重复的排列,即 n 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。

输入格式

一个整数n。

输出格式

由1∼n 组成的所有不重复的数字序列,每行一个序列。

每个数字保留 5个场宽。

输入输出样例

输入 #1

3

输出 #1

    1    2    3
    1    3    2
    2    1    3
    2    3    1
    3    1    2
    3    2    1

说明/提示

1≤n≤9。

解题思路

根据题意,对于全排列问题,以样例n=3为例,可以深度优先DFS搜索方法如图所示。

根据上述搜索过程,设计算法步骤如下:(1)用数组a保存排列,当排列的长度为n时,是一种排列方案,输出即可。(2)用数组vis记录数字是否被使用过,当vis[i]=1时,表示数字i被使用过,否则没有被使用过。 (3)DFS(u)表示已经确定了a的前u个数(从a[1]开始填数),当u>n时,输出搜索的全排列。 注意:在DFS过程中,数组vis既要标记,也要“撤销”标记。

AC 

#include<bits/stdc++.h>
using namespace std;
int a[10],n;
bool vis[10];
void dfs(int u){if(u>n){//当u=n+1时,表示前n个空位已填好数 for(int i=1;i<=n;i++){//输出一种排列方案 cout<<setw(5)<<a[i];}cout<<endl;return;//dfs的终止条件 }for(int i=1;i<=n;i++){if(!vis[i]){a[u]=i;//在第u个空位填上i vis[i]=1;//标记i为已使用 dfs(u+1);//填下一个空位 vis[i]=0;//dfs回来后,要撤销之前的标记 }}
}
int main(){cin>>n;dfs(1);return 0;
}

setw函数

格式:
setw(……)//()内是数字
setw()——打印格式(控制)
setw means:宽度
E.X.
setw(4):
0   0   0   0//每个隔4格
!只适用于打印字符!

洛谷小课堂P1605 迷宫

题目描述

给定一个 N×M 方格的迷宫,迷宫里有T处障碍,障碍处不可通过。

在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。

给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。

输入格式

第一行为三个正整数 N,M,T,分别表示迷宫的长宽和障碍总数。

第二行为四个正整数 SX,SY,FX,FY,SX,SY 代表起点坐标,FX,FY 代表终点坐标。

接下来 T 行,每行两个正整数,表示障碍点的坐标。

输出格式

输出从起点坐标到终点坐标的方案总数。

输入输出样例:

输入 #1

2 2 1
1 1 2 2
1 2

输出 #1

1

说明/提示

对于 100%的数据,1≤N,M≤5,1≤T≤10,1≤SX,FX≤n,1≤SY,FY≤m。

解题思路

这题除了深搜,还是深搜。

深搜,一句话来总结一下,就是:

不撞南墙不回头

而在这题里,“南墙”有三个:

第一个是真墙:迷宫的围墙

也就是俗话所说的越界。越界了你还不回头,你是想去哪儿?

第二个是山墙:障碍物T

如果一障碍物横在你面前,你还是绕路吧!

第三个是人造墙:题目说了每个方格最多只能走一次

这是真没办法

所以深搜的返回条件就出来了——就是以上那三堵墙

我们每次可以从上下左右四个方向进行深搜,一旦遇上南墙就返回。

AC

#include<iostream>
using namespace std;
int n, m, t, sx, sy, fx, fy;
int  vis[10][10]; //标记
int mp[10][10]; //障碍物位置
int ans = 0;
int xx[] = { 1,0,-1,0 };
int yy[] = { 0,-1,0,1 };
void dfs(int x, int y)
{if (x == fx && y == fy){ans++;return;}for (int i = 0; i < 4; i++){int dx = xx[i] + x;int dy = yy[i] + y;if (dx >= 1 && dx <= n && dy >= 1 && dy <= m && vis[dx][dy]==0 && mp[dx][dy]==0){vis[dx][dy] = 1;dfs(dx, dy);vis[dx][dy] = 0;}}
}
int main()
{cin >> n >> m >> t >> sx >> sy >> fx >> fy;while (t--){int a, b;cin >> a >> b;mp[a][b] = 1;}vis[sx][sy] = 1;dfs(sx, sy);cout << ans << endl;return 0;
}

课后练习:洛谷P2404 自然数的拆分问题

题目

自然数的拆分问题 - 洛谷

解题思路

dfs递归求解,假设1到n-1每个数都有n个,现在在这n(n-1)个数里选取任意个数字,使这些数字的和为n,因此这n(n-1)个数只有选和不选两种状态,正是dfs的经典应用,得到的结果可能会有重复的

所有可以用sort和set进行排序和去重步骤

AC

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;
vector<int>a;
string midd;
set<string>h;
int n,t;void dfs(int mid){if(mid==n){         //如果数的累加和等于n就记录该组合t++;vector<int>b(a);   //复制数组asort(b.begin(),b.end());     //排序midd.clear();for(int i=0;i<b.size();i++){          //把整数数组转换成字符串,并存入set里去重midd+=(b[i]+'0');if(i<b.size()-1) midd+='+';}h.insert(midd);}for(int i=1;i<n;i++){if(mid+i<=n){mid+=i;a.push_back(i);dfs(mid);               //每一层都加入i并递归到下一层(选)a.pop_back();           //回溯,使得这一层不加入i(不选)mid-=i;}}
}int main(){cin>>n;dfs(0);for(auto i:h)cout<<i<<endl;return 0;
}

结尾

本篇文章共3767字,如果你能支持一下我,我十分感谢!!!

如果你喜欢或想了解一下其他的算法,可以看看以下这些:

二分:

C++:第十讲二分查找-CSDN博客

前缀和与差分:

C++:第九讲前缀和与差分-CSDN博客

排序:

C++:第七讲冒泡排序-CSDN博客

函数:

C++第6讲max和min函数_c++ min函数-CSDN博客

C++第五讲函数初步-CSDN博客

for循环&数组:

C++第四讲for循环及数组-CSDN博客

if语句&else语句及运算:

C++第三讲:C++中的逻辑运算符及if else语句-CSDN博客

基础:

C++第二讲输入与输出-CSDN博客

C++第一讲认识C++编译器-CSDN博客

最后认识一下,我是爱编程的喷火龙廖,我们有缘再见!

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

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

相关文章

一元函数微分学——刷题(14

目录 1.题目&#xff1a;2.解题思路和步骤&#xff1a;3.总结&#xff1a;小结&#xff1a; 1.题目&#xff1a; 2.解题思路和步骤&#xff1a; 只要知道反函数求导等于原函数的导数的倒数&#xff0c;那就很好求解了&#xff0c;这不过要先处理好x和y的对应关系&#xff0c;知…

本地套接字通信

本地套接字&#xff08;Unix域套接字&#xff09;是用于在同一台机器上的进程之间进行通信的一种方式。它不涉及网络协议&#xff0c;而是直接在文件系统中创建一个套接字文件&#xff0c;进程可以通过该文件进行通信。 本地套接字的作用&#xff1a;本地的进程间通信 有关系的…

语音AI小夜灯项目

一、项目简介 使用ESP32-S3N8R8模块作为主控芯片&#xff0c;S3内核增加了用于加速神经网络计算和信号处理等的指令&#xff0c;这使得我们可以使用它来快速解析训练好的语音模型进行语音识别的功能。 二、原理解析 本项目由四个部分组成&#xff0c;电源部分、LED照明部分、…

uniapp二维码有效期倒计时三分钟的效果是实现

需求&#xff1a; 会员码时效只有3分钟有效期&#xff0c;需要在页面倒计时3分钟&#xff0c;没有长按保存的效果实现 效果&#xff1a; 代码&#xff1a; <templete> <view> <uni-list> <view class"custom-list-item" click"onCode(c…

java代码规范(适合写程序之前先了解有助于开发协同)

目录 一、类定义 二、方法定义 三、接口定义 四、变量定义 1、命名规范&#xff1a; 2、类型规范&#xff1a; 3、常量规范&#xff1a; 五、static关键字 1、静态变量&#xff08;类变量&#xff09;&#xff1a; 2、静态方法&#xff08;类方法&#xff09;&#x…

AUTOSAR软件手册文档缩写描述,AUTOSAR_TR_PredefinedNames

由于AUTOSAR文档中的缩写太多&#xff0c;入门者看起开不方便。例如TR、SWS、SRS、EXP模块。 下载链接&#xff1a;https://www.autosar.org/fileadmin/standards/R21-11/FO/AUTOSAR_TR_PredefinedNames.pdf

android——自定义TextView

效果展示&#xff1a; 代码解析&#xff1a; 1、首先设置自定义属性&#xff08;res/values下新建一个attrs.xml文件&#xff09; <?xml version"1.0" encoding"utf-8"?> <resources><!-- name 自定义view的名字 CustomTextView--&…

Spring Bean的生命周期(钩子函数)

借鉴&#xff1a;https://www.cnblogs.com/liweimingbk/p/17843970.html https://blog.csdn.net/lxz352907839/article/details/128634404 一、Spring Bean生命周期 如果Spring配置文件中所定义的Bean类实现了ApplicationContextAware 接口&#xff0c;那么在加载Spring配置文…

Flood Fill算法总结

算法思想 从一个起点开始&#xff0c;每一次随机选择一个新加进来的格子&#xff0c;看一下它周围能否扩展新的格子。如果能扩展&#xff0c;那么就扩展进来&#xff0c;直到不能扩展新的格子为止。当然需要判重&#xff0c;同样一个格子只能覆盖一次&#xff0c;这样能够保证时…

DataLoader与Dataset

一、人民币二分类 二、DataLoader 与 Dataset DataLoader torch.utils.data.DataLoader 功能&#xff1a;构建可迭代的数据装载器 &#xff08;只标注了较为重要的&#xff09; • dataset: Dataset类&#xff0c;决定数据从哪读取及如何读取 • batchsize : 批大小 • num_…

机器学习异常值处理 逻辑汇总一

一 清除数据中恒定不变值 如果某个数据长时间不变&#xff0c;默认异常&#xff0c;清除掉该部分数据&#xff1a; # 使用 shift 和 cumsum 来创建一个分组键&#xff0c;每次值改变都会增加组号 g (df[沉淀池3号进水流量] ! df[沉淀池3号进水流量].shift()).cumsum()# 使用…

案例253:基于微信小程序的懂球短视频管理系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SpringBoot JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder …

GC8549 大电流,双通道 12V,短地短电源保护等功能 可替代ONSEMI的LV8548/LV8549

GC8549 可以工作在 3.8~12V 的电源电压上&#xff0c;每 通道能提供高达 1.5A 持续输出电流或者 2.5A 峰值 电流&#xff0c;睡眠模式下功耗小于 1uA。具有 PWM&#xff08;IN/EN&#xff09;输入接口,与行业标 准器件兼容&#xff0c;并具有过温保护&#xff0c;欠压保护&…

【计算机网络】网络层

文章目录 网络层提供的服务虚电路数据报服务虚电路与数据报服务比较 虚拟互连网络IP地址IP层次结构IP地址分类特殊地址子网掩码 子网划分变长子网划分超网合并网络规律 IP地址与MAC地址ARP协议ARP欺骗的应用 数据包数据包首部 路由ICMP协议RIP动态路由协议OSPF协议BGP协议 VPNN…

进程等待(wait和wait函数)【Linux】

进程等待 wait和wait函数【Linux】 进程等待的概念进程等待的必要性进程等待的方法wait函数waitpid函数 非阻塞等待和阻塞等待的对比阻塞等待&#xff1a;非阻塞等待 进程等待的概念 进程等待就是通过 wait/waitpid的方式&#xff0c;让父进程对子进程进行等待子进程退出并且将…

【信号处理:小波包转换(WPT)/小波包分解(WPD) 】

【信号处理&#xff1a;小波包转换&#xff08;WPT&#xff09;/小波包分解&#xff08;WPD&#xff09; 】 小波包变换简介WPT/WPD的基础知识WPT/WPD的主要特点The Wavelet Packet Transform 小波包变换前向小波数据包变换最佳基础和成本函数数学中波纹的最佳基础其他成本函数…

酷狗高级Java面试真题

今年IT寒冬&#xff0c;大厂都裁员或者准备裁员&#xff0c;作为开猿节流主要目标之一&#xff0c;我们更应该时刻保持竞争力。为了抱团取暖&#xff0c;林老师开通了《知识星球》&#xff0c;并邀请我阿里、快手、腾讯等的朋友加入&#xff0c;分享八股文、项目经验、管理经验…

洛谷普及组P1044栈,题目讲解(无数论基础,纯打表找规律)

[NOIP2003 普及组] 栈 - 洛谷 我先写了个打表的代码&#xff0c;写了一个小时&#xff0c;o(╥﹏╥)o只能说我真不擅长dfs。 int n; std::unordered_map<std::string, int>map; void dfs(std::vector<int>&a, int step,std::stack<int>p, std::string …

Nginx中include配置文件,方便管理多域名

目录 1.加上include配置 2.配置 server 记录 一个网站对应一个server 记录&#xff0c;这样管理起来相对麻烦。我们可以将每个网站记录单独拆分出来即可&#xff0c;这就需要用到 nginx 中的 conf.d 文件 1.加上include配置 先进入到 nginx.conf 文件&#xff0c;然后将所有…

CentOS7搭建Elasticsearch与Kibana服务

1.部署单点es 1.1.创建网络 因为我们还需要部署kibana容器&#xff0c;因此需要让es和kibana容器互联。这里先创建一个网络&#xff1a; docker network create es-net 1.2拉取elasticsearch镜像 docker pull elasticsearch:7.11.1 1.3.运行 运行docker命令&#xff0c;部…