C++搜索算法(dfs)

news2024/9/20 10:53:09

目录

一.dfs简介

二.dfs的运用

1.迷宫问题

经典题型:最快走出迷宫

题目描述:

数据范围:

题目分析:

正确代码

2.棋盘问题:

经典题型:八皇后问题

题目描述:

题目分析:

正确代码:

3.排列与组合:

经典类题:数字全排列

题目描述:

数据范围:

题目分析:

正确代码:

三.总结


一.dfs简介

深度优先搜索,简称dfs。它在百度上的解释是这样的:

但这跟C++中的dfs关系并不大。在C++中dfs是指对于某一个节点,进行拓展时可能有若干种方式,以深度为第一优先级进行遍历的方式。就像在下图中,我们先将一个节点走到最深处,如果没有路,就返回上一个节点看有没有其他路径,它的搜索路径就是:1-2-3-4-5-6-7-8-9-10-11。

我们通常使用递归来进行搜索,以下为dfs的搜索模板:

#include<bits/stdc++.h>
using namespace std;
char a[10][10];
bool vis[10][10];
int n,m,dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1},ans=INT_MAX;
void dfs(int x,int y,int step){
	if(){//递归出口
		//结束后要做的
	}
	int nx,ny;
	for(int i=1;i<=4;i++){
		nx=x+dx[i],ny=y+dy[i];//坐标移动
		if(nx<1||nx>n||ny<1||ny>m) continue;
		if(a[nx][ny]=='#'||vis[nx][ny]==1) continue;
		vis[nx][ny]=1;
		dfs(nx,ny,step+1);
		vis[nx][ny]=0; 
	}//vis标记以走过的路
}
int main() {
	cin>>n>>m;
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j];
	dfs(1,1,1);
	//输出需要输出的数
	return 0;
}

二.dfs的运用

1.迷宫问题

在进行搜索枚举时,我们知道从初始状态(起点)到最终状态(终点),每一步都做了一次选择,我们可以思考一下,如何将每一步的选择都进行记录,这也就是我们记录搜索的路径。

要记录路径我们可以:

1.记录每一个节点的深度即dfs中增加一个状态。

2.用数组记录每一个深度下的选择。
此时,当某一条路径从s进行dfs搜索到t时,我们就记录了每一步的选择,最后到达终点时,我们便可以进行路径的输出。

经典题型:最快走出迷宫

题目描述:

一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走;
有的格子是空地,可以走。 给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)。
只能在水平方向或垂直方向走,不能斜着走。

数据范围:

1≤ R,C ≤ 10

题目分析:

这就是一道最简单的dfs模板题,我们仅需将所有路径递归出来,再用打擂台的方法求出最小值即可。

正确代码
#include<bits/stdc++.h>
using namespace std;
char a[10][10];
bool vis[10][10];
int n,m,dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1},ans=INT_MAX;
void dfs(int x,int y,int step){
	if(x==n&&y==m){
		ans=min(ans,step);
		return;
	}
	int nx,ny;
	for(int i=1;i<=4;i++){
		nx=x+dx[i],ny=y+dy[i];
		if(nx<1||nx>n||ny<1||ny>m) continue;
		if(a[nx][ny]=='#'||vis[nx][ny]==1) continue;
		vis[nx][ny]=1;
		dfs(nx,ny,step+1);
		vis[nx][ny]=0; 
	}
}
int main() {
	cin>>n>>m;
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j];
	dfs(1,1,1);
	cout<<ans;
	return 0;
}

2.棋盘问题:

经典题型:八皇后问题

题目描述:

在国际象棋棋盘上放置八个皇后,要求每两个皇后之间不能直接吃掉对方。按给定顺序和格式输出所有八皇后问题的解(见样例)。

题目分析:

首先,皇后的走法与其他的棋子不同,她可以横向、纵向和斜向移动,所以要标记就需要她所在的那一行、一列,两斜线。

第二,要注意的是他要输出的是所有情况。

(此图片只是演示,并不是这到题的真正可能)

正确代码:
#include<bits/stdc++.h>
using namespace std;
int a[50][50];
bool x[50],r[50],l[50];
int k;
void dfs(int y){
	if(y==9){
		k++;
		cout<<"No. "<<k<<endl;
		for(int i=1;i<=8;i++){
			for(int j=1;j<=8;j++){
				cout<<a[i][j]<<' ';
			}
			cout<<endl;
		}
		return ;
	}//出口,将坐标转换为图形
	for(int i=1;i<=8;i++){
		if(x[i]||l[i+y]||r[i-y+8])	continue;
		x[i]=l[i+y]=r[i-y+8]=1;
		a[i][y]=1;
		dfs(y+1);
		x[i]=l[i+y]=r[i-y+8]=0;
		a[i][y]=0;
	}//记录坐标
}
int main() {
	dfs(1);
	return 0;
}

3.排列与组合:

排列组合类型的题目就是选与不选的抉择。我们关注的是选了哪些数字(内容)
对于每个数选和不选的两种情况进行两次dfs拓展。组合能枚举到所有情况,但是不关注选择的先后顺序,我们知道选了哪些数,但是顺序是不清晰的。整体复杂度为O(2n)。我们可以使用回溯进行试探性选择,这样就可以枚举出所有不同的选择顺序。

经典类题:数字全排列

题目描述:

在一个集合{ 1,2,3...,n }中,请输出这些数字的所有排列方式.。

数据范围:

n<=10

题目分析:

n个数的全排列,可以理解成做n次选择,每次在[1,n]中选择一个数(选过的不再选)。
这样很容易画出一个树形结构。当所有的数都已经被选完后,则输出当前的选择序列。

正确代码:
#include<bits/stdc++.h>
using namespace std;
int n,shu[15];
bool vis[11];
void dfs(int x){
	if(x==n+1){
		for(int i=1;i<=n;i++){
			cout<<shu[i]<<" ";
		}
		cout<<endl;
		return;
	}
	for(int i=1;i<=n;i++){
		if(vis[i]==true) continue;
		vis[i]=true;
		shu[x]=i;
		dfs(x+1);
		vis[i]=false;
	}
}
int main(){
	cin>>n;
	dfs(1);
	return 0;
}

三.总结

dfs的优点主要包括实现简单、‌易于理解,‌并且适用于解决许多问题。‌

Ⅰ.实现简单、‌易于理解:‌dfs算法的实现逻辑相对直观和简单,‌使得它易于被编程人员理解和实现。‌这种算法适合那些需要递归探索所有可能路径的问题,‌如图的遍历、‌树的搜索等。‌

Ⅱ.适用性问题广泛:‌dfs算法在计算机科学领域有着广泛的应用,‌能够解决包括但不限于图的遍历、‌全排列生成、‌最短路径搜索等问题。‌这些问题的共同特点是需要探索所有可能的状态或路径,‌以找到解决方案或确定是否存在解决方案。‌

尽管dfs算法具有上述优点,‌但它也存在一些潜在的缺点,‌例如可能会陷入无限循环(‌对于非连通图)‌或不一定能找到最短路径等。‌因此,‌在实际应用中,‌选择使用DFS算法还是需要根据具体问题的特性和需求来决定。‌

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

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

相关文章

微服务实战系列之玩转Docker(五)

前言 在我们日常的工作生活中&#xff0c;经常听到的一句话&#xff1a;“是骡子是马拉出来遛遛”。目的是看一个人/物是不是名副其实。我们在使用docker时&#xff0c;也要看看它究竟是如何RUN起来的。当面试官问你的时候&#xff0c;可以如是回答&#xff0c;保你“一文通关…

SQUID - 形状条件下的基于分子片段的3D分子生成等变模型 评测

SQUID 是一个形状条件下基于片段的3D分子生成模型&#xff0c;给一个3D参考分子&#xff0c;SQUID 可以根据参考分子的形状&#xff0c;基于片段库&#xff0c;生成与参考分子形状非常相似的分子。 SQUID 模型来自于 ICLR 2023 文章&#xff08;2022年10月6日提交&#xff09;&…

中国 X86 CPU 技术源自何方

注&#xff1a; 原文发布于 2017 年&#xff0c;两篇合二为一。未与作者沟通&#xff0c;侵权&#xff0c;立删。 导语&#xff1a; Intel 对 X86 的授权有着极为严格的限制&#xff0c;那么上海兆芯的 X86 芯片技术到底从何而来&#xff1f;ZX-C 目前的短板在哪里&#xff1f;…

电子电器架构 --- 智能汽车的大脑(域控制器)

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

【深入理解SpringCloud微服务】浅析微服务注册中心Eureka与nacos,手写实现一个微服务注册中心

【深入理解SpringCloud微服务】浅析微服务注册中心Eureka与nacos&#xff0c;手写实现一个微服务注册中心 注册中心手写实现一个注册中心服务端设计客户端设计 注册中心 注册中心是微服务体系里面非常重要的一个核心组件&#xff0c;它最重要的作用就是实现服务注册与发现。 …

vscode 远程 Ubuntu 系统

1、在 Ubuntu 下检查 sshd 守护进程是否开启 ps -aux | grep sshd如果没有开启&#xff0c;请在 Ubuntu 下输入指令安装 sudo apt-get install openssh-server2、首先打开 Windows 下的 vscode&#xff0c;点击左下角图标打开远程窗口 3、打开远程窗口&#xff0c;选择“Con…

谷粒商城实战笔记-38-前端基础-Vue-指令-单向绑定双向绑定

文章目录 一&#xff0c;插值表达式注意事项1&#xff1a;不适合复杂的逻辑处理注意事项2&#xff1a;插值表达式支持文本拼接注意事项3&#xff1a;插值表达式只能在标签体中 二&#xff0c;v-html和v-textv-textv-html区别总结&#xff1a;最佳实践 三&#xff0c;v-model复选…

论文阅读:Speculative RAG: Enhancing Retrieval Augmented Generation through Drafting

论文地址&#xff1a;https://arxiv.org/abs/2407.08223 RAG 将 LLM 的生成能力与外部知识源相结合&#xff0c;以提供更准确和最新的响应。最近的 RAG 进展侧重于通过迭代 LLM 完善或通过 LLM 的额外指令调整获得自我批判能力来改进检索结果。在这项工作中&#xff0c;作者介…

MySQL:JOIN 多表查询

多表查询 在关系型数据库中&#xff0c;表与表之间是有联系的&#xff0c;它们通过 外键 联系在一起&#xff0c;所以在实际应用中&#xff0c;经常使用多表查询。多表查询就是同时查询两个或两个以上的表。 MySQL多表查询是数据库操作中非常重要的一部分&#xff0c;它允许你…

《从C/C++到Java入门指南》- 17.命令行参数

命令行参数 一直写代码的童鞋可能留意到了&#xff0c;main函数中会传入一个String args[]的字符串数组。 这个数组由JVM接收用户输入并传给main函数。 import java.util.*; public class Main {public static void main(String[] args) {for (String arg : args) {System.out…

[Redis]典型应用——缓存

什么是缓存 缓存&#xff08;Cache&#xff09;是一种用于临时存储数据的机制&#xff0c;目的是提高数据访问速度和系统性能。 核心思路就是把一些常用的数据放到触手可及(访问速度更快)的地方&#xff0c;方便随时读取 缓存是一个相对的概念&#xff0c;比如说&#xff0c…

[CSS] 浮动布局的深入理解与应用

文章目录 浮动的简介元素浮动后的特点解决浮动产生的影响浮动后的影响解决浮动产生的影响 浮动相关属性实际应用示例示例1&#xff1a;图片与文字环绕示例2&#xff1a;多列布局示例3&#xff1a;响应式布局 总结 浮动布局是CSS中一种非常强大的布局方式&#xff0c;最初设计用…

as是python关键字吗

关键字as的作用把紧跟其后的对象代替其前方的一个对象&#xff0c;其作用效果如下所示&#xff1a; import scrapy as tools 这个表达式中就是在当前这个模块中&#xff0c;使用tools可以代替scrapy&#xff0c;相当于C中的宏定义。在该as作用域中&#xff0c;可以使用tools来代…

STM32CubeIDE工程编译提示“has a LOAD segment with RWX permissions”解决办法

0 问题描述 使用STM32CubeIDE进行STM32MP135的开发时&#xff0c;编译过程打印了如下警告&#xff1a; 描述&#xff1a;has a LOAD segment with RWX permissions1 解决办法 右键工程&#xff0c;依次点击Properties->C/C Build->Settings->MCU GCC Linker->M…

如何将PDF转换成可以直接编辑的CAD图纸?

PDF图纸是为了让用户更好的阅览CAD文件&#xff0c;但是&#xff0c;当我们想要对其进行编辑的时候&#xff0c;PDF图纸就是一个麻烦了。那么PDF转换成CAD后可以编辑吗&#xff1f;如何将PDF转换成可以直接编辑的CAD图纸呢&#xff1f;本篇给你答案。 1、启动迅捷CAD编辑器&…

vcs+verdi搭建基础仿真的版本V1

2024-7-20 数字软件安装&#xff0c;仿真环境测试 dut重新修改 makefile重新修改 verdi整合完成 dut.v module dut ( );reg clk;initial beginclk 0;forever begin#10 clk ~clk;endendinitial begin$fsdbDumpfile("verilog.fsdb");$fsdbDumpvars();$vcdpluson;$…

WAAP安全防护能力

利用传统安全漏洞发动攻击的难度不断提升&#xff0c;攻击者的重心从传统的应用漏洞转向无明显攻击特征&#xff0c;模拟合法业务操作的自动化攻击。Web应用程序和API面临众多攻击场景&#xff0c;根据国内的情况进行汇总分析&#xff0c;主要分为恶意爬虫防护、安全攻击防护、…

电脑显示mfc140u.dll丢失的修复方法,总结7种有效的方法

mfc140u.dll是什么&#xff1f;为什么电脑会出现mfc140u.dll丢失&#xff1f;那么mfc140u.dll丢失会给电脑带来什么影响&#xff1f;mfc140u.dll丢失怎么办&#xff1f;今天详细给大家一一探讨一下mfc140u.dll文件与mfc140u.dll丢失的多种不同解决方法分享&#xff01; 一、mfc…

【Espressif-ESP32S3】【VScode】安装【ESP-IDF】插件及相关工具链

一、ESP-IDF简介 二、VScode安装ESP-IDF插件 三、安装ESP-IDF、ESP-IDF-Tools以及相关工具链 四、测试例程&编译烧录 五、IDF常用指令 资料下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/15Q2rl2jpIaKfj5rATkYE6g?pwdGLNG 提取码&#xff1a;GLNG 一、ESP-…

Linux 文件安装的mysql 启动

1、找到my.cnf 2、确定文件类容&#xff1a; 并确保这些重要的配置&#xff1a;basedir 、datadir、socket 文件或目录都存在 3、找到mysqld 位置 4、启动mysqld mysqld --defaults-file/etc/my.cnf --usermysql