搜索与图论-DFS

news2024/11/24 2:01:04

文章目录

  • 一、DFS
    • 1. DFS 简介
    • 2. DFS 的实现步骤
    • 3. DFS 实际演示
  • 二、DFS 例题——排列数字
    • 具体实现
      • 1. 样例演示
      • 2. 实现思路
      • 3. 代码注解
      • 4. 实现代码
  • 三、DFS 例题—— n-皇后问题(经典)
    • 具体实现——按行进行枚举
      • 1. 样例演示
      • 2. 实现思路
      • 3. 代码注解
      • 4. 实现代码
    • 具体实现——按格子进行枚举
      • 1. 实现思路
      • 2. 实现代码

一、DFS

  • DFS 的关键点是递归和回溯。

1. DFS 简介

  • DFS(Depth First Search)是深度优先遍历,是图论当中一种非常重要的算法,生产上广泛用于拓扑排序,寻路(走迷宫),搜索引擎,爬虫等。
  • 定义是,不断地沿着顶点的深度方向遍历。顶点的深度方向是指它的邻接点方向。
  • 主要用于解决是否存在一个我们所需要的结果。因为 DFS 会首先把一种可能的情况尝试到底。才会回溯去尝试下一种情况,只要找到一种情况,就可以返回了。
  • DFS 问题一般分为两类:
  • (1) 定义的 DFS :对图的连通性进行测试,典型的问题:迷宫连通性测试、图的条件搜索等。
  • (2) 广义的 DFS–DFS 思路的应用: DFS 搜索顺序+规则问题、穷举结果寻求最优解/符合条件解等等,由于其穷举答案的本质,又被称为爆搜。

2. DFS 的实现步骤

  • (1) 从顶点出发。
  • (2) 访问顶点,也就是根节点。
  • (3) 依次从顶点的未被访问的邻接点出发,进行深度优先遍历;直至和顶点有路径相通的顶点都被访问。
  • (4) 若此时尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到所有顶点均被访问过为止。

3. DFS 实际演示

在这里插入图片描述

  • (1) 首从根节点 1 开始遍历,它相邻的节点有 2,3,4,先遍历节点 2,再遍历 2 的子节点 5,然后再遍历 5 的子节点 9。

在这里插入图片描述

  • (2) 上图中一条路已经走到底了( 9是叶子节点,再无可遍历的节点 ),此时就从 9 回退到上一个节点 5,看下节点 5 是否还有除 9 以外的节点,没有继续回退到 2,2 也没有除 5 以外的节点,回退到 1,1 有除 2 以外的节点 3,所以从节点 3 开始进行深度优先遍历,如下。

在这里插入图片描述

  • (3) 同理从 10 开始往上回溯到 6, 6 没有除 10 以外的子节点,再往上回溯,发现 3 有除 6 以外的子点 7,所以此时会遍历 7。

在这里插入图片描述

  • (4) 从 7 往上回溯到 3, 1,发现 1 还有节点 4 未遍历,所以此时沿着 4, 8 进行遍历,这样就遍历完成了。
  • (5) 完整的节点的遍历顺序如下(节点上的的蓝色数字代表遍历的顺序)。

在这里插入图片描述

二、DFS 例题——排列数字

题目描述

给定一个整数 n,将数字 1∼n 排成一排,将会有很多种排列方法。
现在,请你按照字典序将所有的排列方法输出。

输入格式

共一行,包含一个整数 n。

输出格式

按字典序输出所有排列方案,每个方案占一行。

数据范围

1 ≤ n ≤ 7

输入样例

3

font size=5> 输出样例

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

具体实现

1. 样例演示

  • 题目当中要求的是将数字 1∼n 排成一排,枚举每一种可能发送的情况。
  • 最开始的时候,三个位置都是空的 _ _ _ 。
  • 首先,填写第一个空位,第一个空位可以填 1 _ _ 。
  • 填好第一个空位,填第二个空位,第二个空位可以填 2,填写后为:1 2 _ 。
  • 填好第二个空位,填第三个空位,第三个空位可以填 3,填写后为: 1 2 3 。
  • 此时,空位填完,无法继续填数,因此,这是第一种方案,输出该方案,然后进行回溯。
  • 退到了状态:1 2 _ 。剩余第三个空位没有填数。第三个空位上除了填过的 3 ,没有其他数字可以填。
  • 因此再往后退一步,退到了状态:1 _ _ 。第二个空位上除了填过的 2,还可以填 3 。第二个空位上填写 3,填写后为:1 3 _ 。
  • 填好第二个空位,填第三个空位,第三个空位可以填 2,填写后为:1 3 2 。
  • 这时候,空位填完,无法继续填数,所以这是第二种方案,输出该方案,然后进行回溯。
  • 然后往后退一步,退到了状态:1 3 _ 。剩余第三个空位没有填数。第三个空位上除了填过的 2,没有其他数字可以填。
  • 因此再往后退一步,退到了状态:1 _ _。第二个空位上除了填过的 2,3,没有其他数字可以填。
  • 因此再往后退一步,退到了状态:_ _ _。第一个空位上除了填过的 1,还可以填 2 和 3 。
  • 2 和 3 的填写方法跟 1 的填写方法相同,在此不做过多叙述,大家可以进行类比思考。
  • 整体流程如下图所示。

在这里插入图片描述

2. 实现思路

  • 详见样例演示。

3. 代码注解

  • st[N] 数组表示数字是否被用过,用 bool 类型对其进行表示,当其为 true 时表示被使用过,当其为 false 时,表示其没有被使用。
  • path[N] 数组保存排列。当排列的长度为 n 时,表明所有位置均已填充,为一种方案,对其进行输出。
  • dfs(i) 表示的含义是在 path[i] 处填写数字,然后递归的在下一个位置填写数字。
  • 回溯是指第 i 个位置填写某个数字的所有情况都遍历后, 第 i 个位置填写下一个数字。
  • 在完成以某一个数字为第一位置所有情况的输出时,要进行回溯,然后要注意将当下情况恢复为原始情况,即 state[N] 变为 false ,尚未使用。在此处,path[i] 不需要进行恢复原样,因为 path[i] 会被覆盖。

4. 实现代码

#include <bits/stdc++.h>
using namespace std;

const int N = 10;

int n;
int path[N];
bool st[N];

void dfs(int u)
{
    if (u == n)
    {
        for (int i = 0; i < n; i ++ )
        {
            cout << path[i] << ' ' ;
        }
        cout << endl;
        return;
    }
    
    for (int i = 1; i <= n; i ++)
    {
        if (!st[i])  //判断这个数是否被使用过
        {
            path[u] = i;
            st[i] = true;
            dfs(u + 1);
            //path[i]不需要进行恢复原样,因为path[i]都会被覆盖。
            st[i] = false;
        }
    }
}

int main()
{
    cin >> n;
    dfs(0);
    system("pause");
    return 0;
}

三、DFS 例题—— n-皇后问题(经典)

题目描述

n − 皇后问题是指将 n 个皇后放在 n×n 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。
在这里插入图片描述
现在给定整数 n,请你输出所有的满足条件的棋子摆法。

输入格式

共一行,包含整数 n。

输出格式

每个解决方案占 n 行,每行输出一个长度为 n 的字符串,用来表示完整的棋盘状态。
其中 . 表示某一个位置的方格状态为空,Q 表示某一个位置的方格上摆着皇后。
每个方案输出完成后,输出一个空行。
注意:行末不能有多余空格。
输出方案的顺序任意,只要不重复且没有遗漏即可。

数据范围

1 ≤ n ≤ 9

输入样例

4

输出样例

.Q…
…Q
Q…
…Q.

…Q.
Q…
…Q
.Q…

具体实现——按行进行枚举

1. 样例演示

  • 具体样例演示如下图:
    在这里插入图片描述

2. 实现思路

  • 首先,从第一行开始看,皇后可以放到哪一列。
  • 然后每一行依次进行枚举。
  • 注意:剪枝,就是提前判断,当前这个方案一定不合法时,直接将与这个方法相关的都完全排除掉。

3. 代码注解

在这里插入图片描述

  • 因为 y-x 可能会是负数,但我们的数组下标不能是负数,所以,在此我们加上偏移量 n ,保证数组下标均为正数。

4. 实现代码

#include <bits/stdc++.h>
using namespace std;

const int N = 20;

int n;
char g[N][N];
bool col[N],dg[N],udg[N];//列,对角线,反对角线

void dfs(int u)
{
    if (u == n)
    {
        for (int i = 0; i < n; i ++ )
        {
            puts(g[i]);
        }
        puts("");
        return;
    }
    
    for (int i = 0; i < n; i ++)
    {
        if (!col[i] && !dg[u + i] && !udg[n - u + i]) 
        {
            g[u][i] = 'Q';
            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);
    system("pause");
    return 0;
}

具体实现——按格子进行枚举

1. 实现思路

  • 对每个格子进行枚举,每个格子都有放或不放两种情况,只要我们枚举到最后一个格子,就可以知道共有几种布局方案了。
    在这里插入图片描述

2. 实现代码

#include <bits/stdc++.h>
using namespace std;

const int N = 20;

int n;
char g[N][N];
bool row[N], col[N], dg[N * 2], udg[N * 2];

void dfs(int x,int y,int s)//x,y 表示坐标,u表示当前有几个皇后
{
    if (s > n) 
    {
        return;
    }
    if (y == n)
    {
        y = 0;
        x ++ ;
    }
    if (x == n)
    {
        if (s == n)
        {
            for (int i = 0; i < n; i ++ ) 
            {
                puts(g[i]);
            }
            puts("");
        }
        return;
    }

//不放皇后
    g[x][y] = '.';
    dfs(x, y + 1, s);

//放皇后
    if (!row[x] && !col[y] && !dg[x + y] && !udg[x - y + n])
    {
        row[x] = col[y] = dg[x + y] = udg[x - y + n] = true;
        g[x][y] = 'Q';
        dfs(x, y + 1, s + 1);
        g[x][y] = '.';
        row[x] = col[y] = dg[x + y] = udg[x - y + n] = false;
    }
}

int main()
{
    cin >> n;
    for(int i = 0; i < n; i ++)
    {
        for(int j = 0;j < n; j ++)
        {
            g[i][j] = '.';
        }
    }
    dfs(0,0,0);
    system("pause");
    return 0;
}

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

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

相关文章

微服务框架 SpringCloud微服务架构 9 初识 Docker 9.4 Docker 的安装

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构9 初识 Docker9.4 Docker 的安装9.4.1 安装Docker9.4.2 启动Docker9.4.3 配…

verilog练习——时序逻辑

目录 VL21 根据状态转移表实现时序电路 VL22 根据状态转移图实现时序电路 VL23 ROM的简单实现 VL24 边沿检测 VL21 根据状态转移表实现时序电路 题目分析&#xff1a; 1、使用三段式状态机&#xff0c;实现更为方便和简洁。 2、三段式和&#xff08;一段式、二段式&#x…

C++GUI之wxWidgets(2)-hello,world

目录wxWidgets的头文件事件main入口函数状态栏事件处理程序wxWidgets的头文件 首先必须包含wxWidgets的头文件。 1、可以在一个文件一个文件的基础上完成(如wx/window.h) 2、使用一个全局包含(wx/wx.h)&#xff0c;其中包括大多数常用的头文件(虽然不是所有的头文件&#xff0…

单变量微积分重点(1)

1.单调有界定理 若数列递增有上界&#xff0c;则数列收敛&#xff08;递减同样&#xff09; 2.海涅定理&#xff08;归结原则&#xff09; 说明&#xff1a;对于任何的属于空心邻域的数列&#xff0c;而且这些数列的极限都是x0. 3.两个重要极限&#xff1a; 4.11个重要极限 导…

基于PHP+MySQL托管中心管理系统的设计与实现

随着在校学生人数的不断增加,学生的数量也在不断的增加,但是很多时候因为父母工作忙没时间,以及一些其他的原因没办法对学生间辅导,这就诞生了托管中心这一行业,但是传统的托管中心多是人工手动的模式进行管理的,这很不科学也不合理,为了改变这一现状,我们开发了托管中心管理系…

SpringBoot_整合Mybatis-plus

一、入门案例 1.准备表结构和数据 准备如下的表结构和相关数据 DROP TABLE IF EXISTS user; ​ CREATE TABLE user (id BIGINT(20) NOT NULL COMMENT 主键ID,name VARCHAR(30) NULL DEFAULT NULL COMMENT 姓名,age INT(11) NULL DEFAULT NULL COMMENT 年龄,email VARCHAR(50) …

Java项目:SSM的KTV管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 主要功能包括&#xff1a; 登陆页,房间信息,房间管理,开取房间,房间查询,会员管理,食物管理,查看订单,查询订单,查看房间消费使用情况等功能。…

随笔荟萃 | sincerity

我们在第一学期中&#xff0c;有一堂经济政治与社会课上&#xff0c;老师给我们讲到共建社会主义和谐社会时&#xff0c;我们现在的社会需要更多的人参与&#xff0c;我又想起班主任陆坚老师对我们全班同学所说的话就是&#xff1a;“我们先做人后做事。”我们如何做人、做人的…

7.7 网络(一)

目录 一 网络是个什么玩意 1 网络很重要&#xff0c;发展很迅速 2 网络是一个很泛的概念 3 我们介绍什么 二 网络技术 1 网络架构 2 网络传输 3 网络安全与管理 网络是操作系统中很重要的一个模块&#xff0c;特别是在现代操作系统中。另外&#xff0c;网络也是软件开发人员必须…

基于PHP+MySQL简历模板下载管理系统

随着时代的发展和进步&#xff0c;互联网络日益成为大众生活的发展方向&#xff0c;每年都有大量的毕业生需要求职&#xff0c;在求职的过程中简历是必不可少的一个环节&#xff0c;但是很多时候求职人员不知道如何更好的制作一份简历&#xff0c;这个情况就需要到网上寻找对应…

OpenCV3图像处理笔记

此笔记针对 Python 版本的 opencv3&#xff0c;c 版本的函数和 python 版本的函数参数几乎一样&#xff0c;只是矩阵格式从 ndarray 类型变成适合 c 的 mat 模板类型。注意&#xff0c;因为 python 版本的opncv只提供接口没有实现&#xff0c;故函数原型还是来自 c版本的opencv…

PlanarSLAM:基于结构化约束的视觉SLAM

1. 摘要 在我们所熟知经典SLAM系统&#xff0c;以ORB-SLAM为代表的通过特征点法在相机位姿估计方面有很好的表现&#xff0c;但在一些人为构造的弱纹理环境下&#xff0c;由于缺少可靠的特征点的缘故&#xff0c;导致表现性能下降。 针对此种问题&#xff0c;作者通过根据周围…

介绍两个LVGL开发工具,让你做出更好的UI

环境 V公众号南山府嵌入式回复4001获取 NXP GUI-Guider 介绍的第一个就是恩智浦官方提供的&#xff0c;现在已经更新到1.4.1版本&#xff0c;相对前面的版本&#xff0c;变化还是挺大的&#xff0c;无论是界面设计还是其他的做的都挺不错的。而且特别好的一点是&#xff0c;支…

深度学习之初识篇——小白也能跑通的深度学习万能框架【重点】

目录深度学习环境配置点击下载深度学习环境数据集准备使用自己标注的数据集使用标注软件数据准备VOC标签格式转yolo格式并划分训练集和测试集部署和训练深度学习项目克隆项目获得预训练权重训练自己的模型启用tensorbord查看参数每文一语本文是作为后续跑深度学习的一个案例教程…

K - Kingdom‘s Power 贪心,E-奇环_牛客练习赛106 二分图 鸽笼原理,F-座位_概率期望,G-交换_dp​​​​​​

K - Kingdoms Power 贪心 一开始想的是要想路程最小&#xff0c;那么他一定是先去征服size最小的子树是最好的&#xff0c;然后就wa了&#xff0c;正解应该是按照深度来贪心&#xff0c;对于一个节点u的子节点&#xff0c;按照u走完子节点的步数进行排序&#xff0c;先从步数小…

年产3000吨冲压型果味硬糖生产车间工艺设计

目 录 摘 要 I Abstract II 1绪论 1 1.1选题概述 1 1.2市场分析 2 1.3设计参数和质量标准 3 1.3.1主要设计参数 3 1.3.2质量标准 3 2工艺流程设计 5 2.1工艺流程图 5 2.2工艺说明 5 2.2.1领料 5 2.2.2化糖 5 2.2.3过滤 6 2.2.4真空熬制 6 2.2.5冷却 6 2.2.6加辅料、调和 7 2.2.…

使用主成分分析进行模态分解(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

HTML入门零基础教程(五)

嗨&#xff0c;大家好&#xff0c;我是异星球的小怪同志 一个想法有点乱七八糟的小怪 如果觉得对你有帮助&#xff0c;请支持一波。 希望未来可以一起学习交流。 目录 一、图像标签 1.图像标签 2.图标标签的其它属性 3.图像标签属性注意点&#xff1a; 一、图像标签 1.…

Unity工具 - 快捷任务栏(Taskbar)

在实际项目中&#xff0c;我们会使用很多的工具。根据工具的来源&#xff0c;可以分为&#xff1a;工程内工具&#xff0c;工程外工具。 工程内的工具&#xff1a;多数是由Unity 提供IMGUI工具包实现的&#xff0c;它使用OnGUI函数以及实现它的脚本来绘制和管理用户界面&#x…

【云服务器 ECS 实战】云服务器新手指南(配置+使用详解)

一、写在前面二、ECS 云服务是什么三、云服务器的购买与配置购买云服务器密码与安全组配置远程连接配置&#xff0c;使网络用户可以访问到服务器在服务器部署自己的网页一、写在前面 谈起云计算&#xff0c;相信大家都不陌生&#xff0c;可以说它已经颠覆了我们生活中的很多应…