【C++算法竞赛】深度优先搜索

目录

算法简介

基本信息

用途

代码思路

思路

代码框架 

算法实战

全排列问题

题目描述

解题思路

题解

八皇后问题

题目描述

解题思路

题解


算法简介

基本信息

深度优先搜索(DFS),全称 Depth-First-Search,属于 图算法 的一种,由 斯坦福大学John E.Hopcroft 和 Robert E.Tarjan 发明。

用途

DFS算法广泛应用于图问题、递归问题、网络爬虫等方面,以下是其中一些应用:

  1. 图的连通性检测:通过DFS可以判断一个图是否是连通的,即从一个节点出发,是否能够访问到所有其他节点。

  2. 图的路径搜索:DFS可以用于寻找从一个节点到目标节点的路径,例如在迷宫中寻找从起点到终点的路径。

  3. 生成树的构建:DFS可以用于生成树的构建,例如最小生成树的Prim算法和Kruskal算法都可以使用DFS。

  4. 深度限制搜索:DFS可以用于在状态空间中搜索满足某种条件的解,例如在八皇后问题中寻找满足条件的解。

  5. 强连通分量的查找:通过DFS可以找到有向图的所有强连通分量,即一组节点,其中任意两个节点之间都存在路径。

  6. 拓扑排序:DFS可以用于有向无环图的拓扑排序,即将图中的节点按照依赖关系进行排序。

  7. 二叉树的遍历:DFS可以用于二叉树的前序、中序和后序遍历。

代码思路

思路

实际上,DFS和暴力枚举有一点像,但是DFS可以剪枝,比枚举更高效。

从第一层开始枚举每一种可能,在可行的方案中继续递归,直到不行获到达底层,开始返回,并记录可行的方案。

注意!!!

1、为防止复杂度过高,一些已经遍历过的子问题,调用之前的结果就行了

2、递归结果返回后,清空之一层的数据,应为这个可能已经否定获记录过了

代码框架 

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

int n, a[10];
bool f[10];

void dfs(int dep) {
    if (//判断到达底层) {
        //记录
    }
    for (int i = 1; i <= n; i++) //遍历每一种可能
    {
        if (//条件) {
            a[dep] = i;
            f[i] = true;
            dfs(dep + 1);//递归
            f[i] = false;
        }
    }
}

int main() {
    dfs(1);
    return 0;
}

算法实战

全排列问题

题目描述

给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。 给定的字符串中的字母已经按照从小到大的顺序排列。

输入格式

输入只有一行,是一个由不同的小写字母组成的字符串,已知字符串的长度在1到6之间。

输出格式

按照字典序输出这个字符串的所有排列方式,每行一个排列。

样例

输入

abc

输出

abc

acb

bac

bca

cab

cba

解题思路

枚举每一位上的每一位数字,如果前面的不重复,则继续递归;每成功一种可能,输出。

题解

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

int n, a[10];
bool f[10];
string s;

void dfs(int dep) {
    if (dep == n + 1) {
        for (int j = 1; j <= n; j++) cout << s[a[j] - 1];
        cout << endl;
        return;
    }
    for (int i = 1; i <= n; i++) {
        if (!f[i]) {
            a[dep] = i;
            f[i] = true;
            dfs(dep + 1);
            f[i] = false;
        }
    }
}

int main() {
    cin >> s;
    n = s.size();
    dfs(1);
    return 0;
}

八皇后问题

题目描述

会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。 
对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b1,b2,...b8,其中bi为相应摆法中第i行皇后所处的列数。已经知道8皇后问题一共有92组解(即92个不同的皇后串)。
给出一个数b,要求输出第b个串。串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小。

输入格式

第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数b(1 <= b <= 92)

输出格式

输出有n行,每行输出对应一个输入。输出应是一个正整数,是对应于b的皇后串。

样例

输入

2
1
92

输出

15863724
84136275

解题思路

先进行dfs,遍历每一行的每一种可能,进行递归,将可行的情况存进数组里,最后根据输入,输出数组中对应的情况。

题解

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

int n, m, a[10], ans, q[100];
bool b[10], c[20], d[20];

void dfs(int i) {
    if (i == 9) {
        ans++;
        for (int j = 1; j <= 8; j++) {
            q[ans] = q[ans] * 10 + a[j];
        }
        return;
    }
    for (int j = 1; j <= 8; j++) {
        if (!b[j] && !c[i + j] && !d[i - j + 7]) {
            a[i] = j;
            b[j] = true;
            c[i + j] = true;
            d[i - j + 7] = true;
            dfs(i + 1);
            a[i] = j;
            b[j] = false;
            c[i + j] = false;
            d[i - j + 7] = false;
        }
    }
}

int main() {
    dfs(1);
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> m;
        cout << q[m] << endl;
    }
    return 0;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Data Structures, Algorithms, and Applications in C++, Second Edition 出版者的话 译者序 前言 第一部分 预备知识 第1章 C++回顾 1.1 引言 1.2 函数与参数 1.2.1 传值参数 1.2.2 模板函数 1.2.3 引用参数 1.2.4 常量引用参数 1.2.5 返回值 1.2.6 重载函数 1.3 异常 1.3.1 抛出异常 1.3.2 处理异常 1.4 动态存储空间分配 1.4.1 操作符new 1.4.2 一维数组 1.4.3 异常处理 1.4.4 操作符delete 1.4.5 二维数组 1.5 自有数据类型 1.5.1 类currency 1.5.2 一种不同的描述方法 1.5.3 操作符重载 1.5.4 友元和保护性类成员 1.5.5 增加#ifndef、#define和#endif语句 1.6 异常类illegalParameterValue 1.7 递归函数 1.7.1 递归的数学函数 1.7.2 归纳 1.7.3 C++递归函数 1.8 标准模板库 1.9 测试与调试 1.9.1 什么是测试 1.9.2 测试数据的设计 1.9.3 调试 1.10 参考及推荐读物 第2章 程序性能分析 2.1 什么是程序性能 2.2 空间复杂度 2.2.1 空间复杂度的组成 2.2.2 举例 2.3 时间复杂度 2.3.1 时间复杂度的组成 2.3.2 操作计数 2.3.3 最好、最坏和平均操作计数 2.3.4 步数 第3章 渐近记法 3.1 引言 3.2 渐近记法 3.2.1 大Ο记法 3.2.2 渐近记法Ω和Θ 3.3 渐近数学(可选) 3.3.1 大O记法 3.3.2 Ω记法 3.3.3 Θ记法 3.3.4 小ο记法 3.3.5 特性 3.4 复杂度分析举例 3.5 实际复杂度 3.6 参考及推荐读物 第4章 性能测量 4.1 引言 4.2 选择实例的大小 4.3 设计测试数据 4.4 实验设计 4.5 高速缓存 4.5.1 简单计算机模型 4.5.2 缓存未命中对运行时间的影响 4.5.3 矩阵乘法 4.6 参考及推荐读物 第二部分 数据结构 第5章 线性表——数组描述 5.1 数据对象和数据结构 5.2 线性表数据结构 5.2.1 抽象数据类型linearList 5.2.2 抽象类linearList 5.3 数组描述 5.3.1 描述 5.3.2 变长一维数组 5.3.3 类arrayList 5.3.4 C++迭代器 5.3.5 arrayList的一个迭代器 5.4 vector的描述 5.5 在一个数组中实现的多重表 5.6 性能测量 5.7 参考及推荐读物 第6章 线性表——链式描述 6.1 单向链表 6.1.1 描述 6.1.2 结构chainNode 6.1.3 类chain 6.1.4 抽象数据类型linearList的扩充 6.1.5 类extendedChain 6.1.6 性能测量 6.2 循环链表和头节点 6.3 双向链表 6.4 链表用到的词汇表 6.5 应用 6.5.1 箱子排序 6.5.2 基数排序 6.5.3 凸包 6.5.4 并查集 第7章 数组和矩阵 7.1 数组 7.1.1 抽象数据类型 7.1.2 C++数组的索引 7.1.3 行主映射和列主映射 7.1.4 用数组的数组来描述 7.1.5 行主描述和列主描述 7.1.6 不规则二维数组 7.2 矩阵 7.2.1 定义和操作 7.2.2 类matrix 7.3 特殊矩阵 7.3.1 定义和应用 7.3.2 对角矩阵 7.3.3 三对角矩阵 7.3.4 三角矩阵 7.3.5 对称矩阵 7.4 稀疏矩阵 7.4.1 基本概念 7.4.2 用单个线性表描述 7.4.3 用多个线性表描述 7.4.4 性能测量 第8章 栈 8.1 定义和应用 8.2 抽象数据类型 8.3 数组描述 8.3.1 作为一个派生类实现 8.3.2 类arrayStack 8.3.3 性能测量 8.4 链表描述 8.4.1 类derivedLinkedStack 8.4.2 类linkedStack 8.4.3 性能测量 8.5 应用 8.5.1 括号匹配 8.5.2 汉诺塔 8.5.3 列车车厢重排 8.5.4 开关盒布线 8.5.5 离线等价类问题 8.5.6 迷宫老鼠 8.6 参考及推荐读物 第9章 队列 9.1 定义和应用 9.2 抽象数据类型 9.3 数组描述 9.3.1 描述 9.3.2 类arrayQueue 9.4 链表描述 9.5 应用 9.5.1 列车车厢重排 9.5.2 电路布线 9.5.3 图元识别 9.5.4 工厂仿真 9.6 参考及推荐读物 第10章
深度优先搜索DFS)是一种用于图和树的遍历算法,它按照深度优先的方式进行搜索。在DFS算法中,我们从一个起始节点开始,沿着一条路径一直向下搜索,直到达到最深的节点,然后回溯到上一个节点,继续搜索其他路径,直到找到问题的解或者遍历完所有可能的路径。 以下是一个使用C++实现深度优先搜索算法的示例: ```cpp #include <iostream> #include <vector> using namespace std; // 定义图的邻接表表示 class Graph { private: int V; // 图的顶点数 vector<vector<int>> adj; // 邻接表 public: Graph(int v) { V = v; adj.resize(V); } // 添加边 void addEdge(int u, int v) { adj[u].push_back(v); adj[v].push_back(u); } // 深度优先搜索 void DFS(int v, vector<bool>& visited) { visited[v] = true; cout << v << " "; // 递归访问邻接节点 for (int i = 0; i < adj[v].size(); i++) { int u = adj[v][i]; if (!visited[u]) { DFS(u, visited); } } } // 对图进行深度优先搜索 void DFS() { vector<bool> visited(V, false); // 记录节点是否被访问过 // 从每个未被访问的节点开始进行DFS for (int v = 0; v < V; v++) { if (!visited[v]) { DFS(v, visited); } } } }; int main() { // 创建一个包含5个节点的图 Graph g(5); // 添加边 g.addEdge(0, 1); g.addEdge(0, 2); g.addEdge(1, 3); g.addEdge(1, 4); // 对图进行深度优先搜索 cout << "DFS traversal: "; g.DFS(); return 0; } ``` 输出结果为: ``` DFS traversal: 0 1 3 4 2 ``` 这是一个简单的深度优先搜索算法的示例,它通过邻接表表示图,并从每个未被访问的节点开始进行深度优先搜索。在搜索过程中,我们使用一个visited数组来记录节点是否被访问过,以避免重复访问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值