【Algorithm | 0x03 搜索与图论】DFS

DFS

        • 基础知识
        • 典型例题
          • 例1:n皇后问题
          • 例2:拍照
          • 例3:理发

基础知识

核心原理:一条路走到黑

示意图:其含义表示,在这个图中顶层是第0层,也就是后面dfs的入口,一般从dfs(0)开始操作。

在这里插入图片描述

模版:

#include <iostream>using namespace std;/*** DFS* 给定一个整数 n,将数字 1∼n* 排成一排,将会有很多种排列方法。* 现在,请你按照字典序将所有的排列方法输出。*/const int N = 10;
int n;
int path[N];    // 路径
bool st[N];     // 元素是否访问过void dfs(int u){// 当前记录的数字个数到达n层 可以输出一种情况了if (u == n){for (int i = 0; i < n; i++){printf("%d ", path[i]);}printf("\n");}//还可以继续dfs搜索 这里的i是放的数值 从1~n嘛for (int i = 1; i <= n; i ++){// 如果当前层没有被使用过if(!st[i]){path[u] = i;     //假设当前层放数值i进行尝试st[i] = true;    //标记访问过了dfs(u + 1);      //继续下一层// 一定要恢复现场st[i] = false;}}
}int main(){cin >> n;dfs(0);  //从顶层也就是第0层开始return 0;
}
典型例题
例1:n皇后问题

非常经典的问题,指将n个皇后放在n * n的国际象棋棋盘上,任意两个皇后不能处于同一行、同一列或同一斜线上。

我们的策略是一行一行的试,比如在第一行的时候,我们尝试把第一个皇后放在所有列上的后续情况全部尝试一边,注意在这个过程中如果遇到不符合题目的情况需要及时剪枝。

在这里插入图片描述

在判断的过程中,除了行和列不能重复,最关键的是对角线的处理,这个分为对角线和反对角线,参考y = ax + b这条直线的截距进行理解
在这里插入图片描述
在这里插入图片描述

最终代码:

#include <iostream>using namespace std;const int N = 20;
int n;
char g[N][N];   // 记录方案 使用字符串记录 
bool col[N], dg[N], udg[N];     // 标记  当前列是否放置过 当前对角线是否放置 当前反对角线是否放置 行不用考虑 因为dfs逐层下搜void dfs(int u){// 当前记录的数字个数到达n层 可以输出一种情况了if (u == n){for (int i = 0; i < n; i++){puts(g[i]);}printf("\n");}//还可以继续dfs搜索 这里的i是放的列值 从0~n-1嘛   对角线怎么设置的for (int i = 0; i < n; i ++){// 如果当前列 对角线 反对角线没有被使用过if(!col[i] && !dg[u + i] && !udg[n - u + i]){g[u][i] = 'Q';     //假设当前行u 的第i列可以放置col[i] = dg[u + i] = udg[n - u + i] = true;    //标记访问过了  注意对角线dfs(u + 1);      //继续下一层// 一定要恢复现场col[i] = dg[u + i] = udg[n - u + i] = false;g[u][i] = '.';}}
}int main(){cin >> n;for (int i = 0; i < n; i ++){for (int j = 0; j < n; j++){g[i][j] = '.';}}dfs(0);  //从顶层也就是第0层开始return 0;
}

方法2:每一个格子进行枚举

这个的思想就是每个格子都尝试一下能不能放皇后,遍历所有情况。

在这里插入图片描述

#include <iostream>using namespace std;const int N = 20;
int n;
char g[N][N];
bool row[N], col[N], dg[N], udg[N];// x 是行  y是列 s是当前摆下的皇后的个数
void dfs(int x, int y, int s){if (y == n){// 越界后 直接切换到下一行的第一个位置x ++;y = 0;}if (x == n){if (s == n){//完全摆完了 可以进行输出for (int i = 0; i < n; i ++){puts(g[i]);}printf("\n");}return;   //这里一定要记得return 因为还没完全结束所有情况}//正常走到这个格子了 下面就两种操作 一个是放皇后 一个是不放// 尝试不放 直接下一个// dfs(x, y ++, s);  这里太吓人了  一定不能用这种自增 要不然就死循环了dfs(x, y + 1, s);// 尝试放皇后 需要看能否放if (!row[x] && !col[y] && !dg[x + y] && !udg[x - y + n]){g[x][y] = 'Q';row[x] = col[y] = dg[x + y] = udg[x - y + n] = true;// 下一个// dfs(x, y ++, s ++);dfs(x, y + 1, s + 1);// 恢复现场row[x] = col[y] = dg[x + y] = udg[x - y + n] = false;g[x][y] = '.';}}int main(){cin >> n;for (int i = 0; i < n; i ++){for (int j = 0; j < n; j ++){g[i][j] = '.';}}// 0行 0列 也就是第一个格子  当前放置的皇后数为0;dfs(0, 0, 0);return 0;
}
例2:拍照

题面:小 A、小 B、小 C、小 D、小 E 五个人 拍照,我们会输入一些前提条件,当id为1的时候,表示后面跟的两个字母对应的人需要相邻,id为2的时候,后面跟的两个字母对应的人需要相隔,最终输出多少种拍照方案

思考转换:

转换为dfs进行求解,就是把这5个人进行排序,比如先尝试把A放在第一个位置,后面尝试所有站位可能,在这个过程中,我们需要借助限制选项,比如相邻还是相隔,可以实现提前剪枝,如果当前的站位方案不符合限制条件,也就是过不了我们的check函数,就直接剪掉。

最终代码:

#include <iostream>using namespace std;/*** 小 A、小 B、小 C、小 D、小 E 五个人 * 转换成dfs 就相当于5个人排位置  只不过添加了一些限制条件 进行剪枝*/// 整个结构体
struct limit{int id;char x, y;
}a[100];int res;
bool vis[105];
int path[1005];
int m;bool check(){// 遍历检查限制for (int i = 0; i < m; i ++){int id = a[i].id, x = a[i].x - 'A' + 1, y = a[i].y - 'A' + 1;// 这里一定要分清 位置和人物标号的关系int posx = 0, posy = 0;for (int i = 1; i <= 5; i ++){if (path[i] == x){posx = i;}if (path[i] == y){posy = i;}}// 这是要相邻if (id == 1){// 思考 path[x] 代表的含义 我们应该找出第x个人所在的位置if (abs(posx - posy) > 1){return false;  //没有相邻}}// 必须不能相邻if (id == 2){if (abs(posx - posy) == 1){return false;  //没有相邻}}}return true;
}
void dfs(int x){if (x == 5){if (check()){res ++;}   return;   // 当前结束,方案可能有多种,直接回退测试下一个方案}// 尝试着5个人都放在当前位置for (int i = 1; i <= 5; i ++){if (!vis[i]){path[x] = i;   // 第x这个位置 放在第i个人vis[i] = true;dfs(x + 1);vis[i] = false;}}}int main(){cin >> m;for (int i = 0; i < m; i ++){cin >> a[i].id >> a[i].x >> a[i].y;}dfs(0);  // 从顶层 也就是第0层开始cout << res;return 0;
}
例3:理发

题面:

在这里插入图片描述

思考转换:这个转换的思路在于选定一个标准进行dfs,因为先进行洗头,所有人都要先洗头,我们就把洗头的顺序作为dfs执行的标准,尝试所有顾客开始洗头的顺序,洗头确定之后,可以覆盖所有组合情况,后面剪头就只能按照实际情况进行,不断更新记录用时最短的方案。

最终代码:

#include <iostream>
#include <queue>using namespace std;const int N = 11;
int a[N], b[N];  //洗发和剪发
int n;
int res = 1e9;   
int path[1005];
bool vis[105];// 首先可以明白 我们dfs的对象是什么 是洗头的顺序安排剩下的剪头只能被迫安排
void dfs(int x){if (x == n){int y1 = 0, y2 = 0;   // 洗头顺序固定的情况下 寻找最短总时间priority_queue<int> q;for (int i = 0; i < n; i ++){int peo = path[i];  //第i个人y1 += a[peo];         // 第i个人洗发// 剪发时间 进入优先队列q.push(b[peo]);y2 = max(y2, y1);  // y2是担心之前还有人没剪完头int w = q.top();    //剪发 读队中头 自动排序 最大的  读完pop出队q.pop();        y2 += w;   }res = min(y2, res);return;}for (int i = 0; i < n; i ++){if (!vis[i]){vis[i] = true;path[x] = i;   // 谁都有机会放在第一个 dfs(x + 1);vis[i] = false;}}
}int main(){int t;cin >> t;while (t --){cin >> n;res = 1e9;for (int i = 0; i < n; i ++){cin >> a[i] >> b[i];}dfs(0);cout << res << endl;}return 0;
}

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

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

相关文章

Redis的数据过期策略有哪些?

Redis内部通过两种主要策略来处理过期的Key&#xff1a; 惰性删除 惰性删除&#xff1a;顾明思议并不是在TTL到期后就立刻删除&#xff0c;而是在访问一个key的时候&#xff0c;Redis会先检查这个键是否过期。如果过期&#xff0c;就删除它&#xff0c;然后返回nil。 这种方式非…

水库雨水情测报和大坝安全监测系统解决方案

一、方案背景 在全球气候变化和极端天气频发的背景下&#xff0c;水库作为重要的水利设施&#xff0c;承担着防洪、供水、灌溉、发电等多重功能。然而&#xff0c;由于水库蓄水量巨大&#xff0c;一旦发生溃坝或运行异常&#xff0c;将对下游地区造成不可估量的生命财产损失。因…

BFS 和 DFS 编程思想、框架、技巧及经典例题总结

BFS 和 DFS 编程思想、框架、技巧及经典例题总结 一、核心编程思想 BFS&#xff08;广度优先搜索&#xff09; 核心思想&#xff1a;以「层次遍历」为核心&#xff0c;从起点出发&#xff0c;优先探索距离起点最近的节点&#xff0c;逐层扩散遍历。本质&#xff1a;通过「队列」…

【面试场景题】日志去重与统计系统设计

文章目录题目场景描述要求问题考察点解答思考一、核心解决方案&#xff08;基础版&#xff0c;单节点32GB内存、10台节点&#xff09;1. 整体架构选型2. 关键步骤详解&#xff08;1&#xff09;数据分片&#xff1a;解决“数据量大&#xff0c;单节点处理不了”的问题&#xff…

【Day 16】Linux-性能查看

目录 一、Stress系统压力测试工具 二、性能查看 &#xff08;一&#xff09;查看CPU # nproc # lscpu # top # uptime # mpstat 数字1 数字2 &#xff08;二&#xff09;查看内存 # dmidecode -t memory | less # free -h # …

【ICCV2017】Deformable Convolutional Networks

一、摘要尽管卷积神经网络&#xff08;CNN&#xff09;在视觉识别任务上取得巨大成功&#xff0c;但其固有的固定几何结构&#xff08;固定卷积采样网格、固定池化窗口、固定 RoI 划分&#xff09;严重限制了对未知几何变换&#xff08;尺度、姿态、形变、视角变化&#xff09;…

echarts在前后端分离项目中的实践与应用

目录 一、ECharts简介 二、后端数据接口设计 三、数据结构设计 1. 柱状图数据结构 2. 饼图数据结构 四、后端实现要点 五、前端ECharts配置解析 1. 柱状图配置 2. 饼图配置 六、最佳实践建议 七、总结 一、ECharts简介 ECharts是百度开源的一个基于JavaScript的可视…

SQL 四大语言分类详解:DDL、DML、DCL、DQL

SQL&#xff08;结构化查询语言&#xff09;通常被分为四种主要类型&#xff0c;每种类型负责不同的数据库操作。下面我将详细介绍这四类SQL语言的语法和用途。一、DDL (Data Definition Language) 数据定义语言功能&#xff1a;定义和管理数据库对象结构&#xff08;表、视图、…

ESP-idf框架下的HTTP服务器\HTML 485温湿度采集并长传

项目描述:本项目采用485采集温湿度以及电压电流等,485模块分别为下图,串口转485模块采用自动收发模块,ESP32工作在AP热点模式,通过手机连接esp32的热点来和esp进行数据通讯,使用esp32作为HTTP服务器缺陷:项目的最终HTML页面代码可发给AI让其写注释#include "freertos/Free…

雅江工程解锁墨脱秘境:基础条件全展示(区位、地震、景点、天气)

目录 前言 一、区位信息 1、空间位置 2、区位介绍 二、地震信息 1、历史地震信息 2、5.0级以上大地震 三、景点信息 1、景点列表分布 2、4A级以上景点 四、天气信息 1、天气实况 2、天气应对挑战 五、总结 前言 相信最近大家对雅江电站的超级大工程项目应该有所耳…

​​机器学习贝叶斯算法

​​一、引言​​在当今机器学习领域&#xff0c;贝叶斯算法犹如一颗璀璨的明星。你是否想过&#xff0c;垃圾邮件过滤系统是如何准确判断一封邮件是否为垃圾邮件的呢&#xff1f;这背后可能就有贝叶斯算法的功劳。今天&#xff0c;我们就一同走进贝叶斯算法的世界&#xff0c;…

Chisel芯片开发入门系列 -- 18. CPU芯片开发和解释8(流水线架构的代码级理解)

以【5 Stage pipeline CPU】搜索图片&#xff0c;选取5幅有代表性的图列举如下&#xff0c;并结合Chisel代码进行理解和点评。 图1&#xff1a;原文链接如下 https://acsweb.ucsd.edu/~dol031/posts/update/2023/04/10/5stage-cpu-pipeline.html 点评&#xff1a;黑色的部分…

Docker容器中文PDF生成解决方案

在Docker容器中生成包含中文内容的PDF文件时&#xff0c;经常遇到中文字符显示为方块或乱码的问题。本文将详细介绍如何在Docker环境中配置中文字体支持&#xff0c;实现完美的中文PDF生成。 问题现象 当使用wkhtmltopdf、Puppeteer或其他PDF生成工具时&#xff1a; 中文字符…

2.java集合,线程面试题(已实践,目前已找到工作)

1线程的创建方式 继承Thread类实现Runnable接口实现Callable接口 2.这三种方式在项目中的使用有哪些&#xff0c;一般都是怎么用的 继承thread类实现线程的方式通过实现run方法来实现线程&#xff0c;通过run进行线程的启用实现runnable方法实现run方法&#xff0c;然后通过thr…

站在前端的角度,看鸿蒙页面布局

从Web前端转向鸿蒙&#xff08;HarmonyOS&#xff09;开发时&#xff0c;理解其页面布局的相似与差异是快速上手的核心。鸿蒙的ArkUI框架在布局理念上与Web前端有诸多相通之处&#xff0c;但也存在关键区别。以下从五个维度系统分析&#xff1a; &#x1f4e6; 一、盒子模型&a…

JavaWeb遗传算法、TSP、模拟退火、ACO算法等实战应用

Java Web中实现遗传算法的应用 以下是关于Java Web中实现遗传算法的应用场景和实例的整理,涵盖不同领域的解决方案和实现方法: 遗传算法基础结构 在Java Web中实现遗传算法通常需要以下核心组件: 种群初始化:随机生成初始解集。 适应度函数:评估个体优劣。 选择操作:轮…

【图像算法 - 09】基于深度学习的烟雾检测:从算法原理到工程实现,完整实战指南

一、项目背景与需求 视频介绍 【图像算法 - 09】基于深度学习的烟雾检测&#xff1a;从算法原理到工程实现&#xff0c;完整实战指南今天我们使用深度学习来训练一个烟雾明火检测系统。这次我们使用了大概一万五千张图片的数据集训练了这次的基于深度学习的烟雾明火检测模型&a…

间接制冷技术概念及特征

1、基本概念 (1)间接制冷技术即二次制冷技术。常规做法:二次冷却液储液罐增加放置于制冷系统管路,促使冷量再快捷的传递给载冷剂,继而载冷剂冷量促使冷库达到制冷效果。间接制冷技术:通过常压的二次冷却介质进行大循环传送冷量,在直接制冷剂不易应用的位置或者不可运用直…

Antlr学习笔记 01、maven配置Antlr4插件案例Demo

文章目录前言源码插件描述pom引入插件案例&#xff1a;实现hello 标识符 案例1、引入Antlr4的pom运行依赖2、定义语义语法&#xff0c;配置.g4文件实现java代码3、编写完之后&#xff0c;执行命令实现编译4、编写单测测试使用参考文章资料获取前言 博主介绍&#xff1a;✌目前…

PostGIS面试题及详细答案120道之 (101-110 )

《前后端面试题》专栏集合了前后端各个知识模块的面试题&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…