news 2026/6/5 13:22:23

《算法竞赛从入门到国奖》算法基础:搜索-DFS初识

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
《算法竞赛从入门到国奖》算法基础:搜索-DFS初识

💡Yupureki:个人主页

✨个人专栏:《C++》 《算法》


🌸Yupureki🌸的简介:


目录

前言

1. 选数

算法原理

实操代码

2. 飞机降落

算法原理

实操代码

3. 八皇后 Checker Challenge

算法原理

实操代码


前言

DFS全称深度优先搜索,相当于是函数递归。其核心思想为"尽可能深"地搜索分支,直到遇到尽头再回溯

1. 选数

题目链接:

P1036 [NOIP 2002 普及组] 选数 - 洛谷

算法原理

对于每个数我们都有两种选择:选和不选

因此我们用dfs,枚举所有选择的情况,当选择的个数为3没有数可选时返回

当然我们选择数也不是乱选,我们在dfs函数中添加一个参数pos,为从数组下标为pos的位置开始选数

由于要统计实时的选择的数的总和以及选择的个数,因此我们定义:

  • sum为选择的数的总和
  • cnt为选择的数的个数
  • ret为总和为素数的结果

当cnt == 3时,判断sum是否为素数,因此要自己实现一个判断素数的函数

实操代码

#include <iostream> #include <vector> #include <cmath> using namespace std; vector<int> v; int n, k; int sum = 0; int cnt = 0; int ret = 0; bool isprime(int num)//判断是否为素数 { if (num <= 1)return false; if (num <= 3)return true; if (num % 2 == 0 || num % 3 == 0)return false; for(int i = 5; i <= sqrt(num);i++) { if (num % i == 0) return false; } return true; } void dfs(int pos)//从下标为pos的位置开始选数 { if (cnt == k) { if (isprime(sum)) ret++; return; } for (int i = pos; i < n; i++) { sum += v[i]; cnt++; dfs(i + 1); cnt--; sum -= v[i]; } return; } int main() { cin >> n >> k; for (int i = 0; i < n; i++) { int num = 0; cin >> num; v.push_back(num); } dfs(0); cout << ret; return 0; }

2. 飞机降落

题目链接:

P9241 [蓝桥杯 2023 省 B] 飞机降落 - 洛谷

算法原理

由于bfs是暴力枚举,因此使用bfs的前提是数据量不能大,一般10到20是合适的

而这个时候发现T小于或等于10,因此可以无脑使用bfs

我们枚举所有的飞机先后降落顺序的全排列,当安排完后进行判断:

  • 如果无法正常降落,回退继续枚举
  • 如果可以正常降落,直接退出bfs

当全排列的时候,每一次递归我们只能选择没有选过的飞机并且我们得全部选上,因此我们得用一个bool数组,来记录哪些飞机选了,哪些飞机没选

实操代码

#include <iostream> #include <vector> using namespace std; int n; vector<int> T; vector<int> D; vector<int> L; vector<int> ret; vector<bool> st;//飞机是否选中:true为选了;false为没选 bool check() { int time = T[ret[0]]; for (auto& it : ret) { int curtime = max(time,T[it]); if(curtime > T[it] + D[it]) return false; time = curtime + L[it]; } return true; } bool dfs() { if (ret.size() == n) { if (check()) { cout << "YES"<<endl; return true; } return false; } for (int i = 0; i < n; i++) { if (st[i] == false)//当飞机没选时,选上 { ret.push_back(i); st[i] = true; if (dfs()) return true; ret.pop_back(); st[i] = false; } } return false; } int main() { int group; cin >> group; while (group--) { T.clear(); D.clear(); L.clear(); st.clear(); ret.clear(); cin >> n; st.resize(n); for (int i = 0; i < n; i++) { int a, b, c; cin >> a >> b >> c; T.push_back(a); D.push_back(b); L.push_back(c); } if (dfs() == false) cout << "NO" << endl; } return 0; }

3. 八皇后 Checker Challenge

题目链接:

P1219 [USACO1.5] 八皇后 Checker Challenge - 洛谷

算法原理

我们先一行一行地选择,每一行选择的情况必须满足以下条件:

  • 每一列只有一个
  • 每一条对角线只有一个

返回条件:

如果在一行发现没有可选的情况,则直接返回;

当最后一行选择完成后,就算这个选法是对的,随后记录下来

保证每一列只有一个是很好判断的,重点是如何判断对角线的情况

根据初中的平面直角坐标系,我们可以得到:两条对角线的方程

我们把两条直线x = 0和x = n分别当作每条对角线的映射关系:

y = -x + (i + j)打在x = 0上的点的集合表示该对角线的选择情况

y = x + (j - i)打在x = n上的带你的集合表示该对角线的选择情况

对应在数组中,即

  • y[j- i + n] = true,表示y = x + (j - i)这条「主对角线」上放置了一个皇后;
  • x[j + i] = true,表示y = -x + (i + j)这条「副对角线」上放置了一个皇后。

实操代码

#include <iostream> #include <vector> using namespace std; int n; int ret = 0; vector<int> v; vector<bool> st; vector<bool> x; vector<bool> y; void dfs() { if (v.size() == n) { ret++; if (ret <= 3) { for (auto& it : v) cout << it + 1 << " "; cout << endl; } return; } for (int i = 0; i < n; i++) { if (st[i] == false && x[i + v.size()] == false && y[i - v.size() + n] == false) { x[i + v.size()] = true; y[i - v.size() + n] = true; v.push_back(i); st[i] = true; dfs(); v.pop_back(); x[i + v.size()] = false; y[i - v.size() + n] = false; st[i] = false; } } return; } int main() { cin >> n; st.resize(n,false); x.resize(2 * n, false); y.resize(2 * n, false); dfs(); cout << ret; return 0; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/31 18:39:29

大数据领域Kafka的数据备份与恢复

知识金字塔构建者&#xff1a;Kafka数据备份与恢复的底层逻辑与实践指南 1. 引入与连接&#xff1a;当Kafka集群崩溃时&#xff0c;我们该如何拯救数据&#xff1f; 1.1 一个让工程师冒冷汗的场景 想象一下&#xff1a;你是某电商公司的大数据工程师&#xff0c;正值618大促高峰…

作者头像 李华
网站建设 2026/5/30 19:32:38

组织本地化部署AI系统需系统性规划与专业技术知识

随着人工智能技术迅猛发展&#xff0c;越来越多组织着手考虑于本地环境里部署、搭建AI系统。这般本地化地部署&#xff0c;不但能够更为妥善地契合数据安全以及隐私保护的要求&#xff0c;而且还能够依照具体业务需求予以深度定制。然而&#xff0c;AI系统搭建属于一个牵涉硬件…

作者头像 李华
网站建设 2026/5/29 15:53:41

vue2 表格如何使用 vxe-table 带列头复制单元格内容同步到 excel 中

vue2 表格如何使用 vxe-table 带列头复制单元格内容同步到 excel 中&#xff0c;vxe-table 本身是支持该功能的&#xff0c;通过设置 clip-config.isCopyHeader 启用复制时带列头信息。 https://vxetable.cn 复制粘贴&#xff0c;通过 keyboard-config.isClip 启用,复制带列头…

作者头像 李华
网站建设 2026/5/20 20:36:45

习题与总结

天平 &#xff08;UVa 839 Not so Mobile&#xff09; 递归向下&#xff1a;遇到重量为 0 就深入子树 回溯向上&#xff1a;子树返回自己的总重量和平衡状态 自底向上计算&#xff1a;叶子节点先计算&#xff0c;父节点依赖子节点的结果 #include <bits/stdc.h> usin…

作者头像 李华
网站建设 2026/6/3 17:08:34

为macOS Finder提供直观的剪切粘贴体验

✨ 简介 FinderClip 是一个轻量级的 macOS 菜单栏应用&#xff0c;让你可以在 Finder 中使用熟悉的 ⌘X 和 ⌘V 快捷键来剪切和移动文件&#xff0c;就像在 Windows 中一样自然。 前往GitHub仓库下载 &#x1f3af; 功能特点 功能说明✂️ 真正的剪切在 Finder 中使用 ⌘X 剪…

作者头像 李华