当前位置: 首页 > news >正文

蓝桥杯备赛(搜索)

·DFS基础&回溯

回溯法简介

回溯法一般使用DFS(深度优先搜索)实现,DFS是一种遍历或搜索图、树或图像等数据结
构的算法,当然这个图、树未必要存储下来(隐式处理就是回溯法),常见的是通过某种关系构造出的搜索树,搜索树一般是排列型搜索树(总节点个数一般为n!级别)和子集型搜索树(总节点个数一般为2^n级别)。
排列型就是每次枚举选哪个,子集型就是对于每一个元素选或不选(结果与顺序无关)。
 DFS从起始节点开始,沿着一条路径尽可能深入地搜索(一条路走到黑),直到无法继续为
止,然后回溯到前一个节点,继续探索其他路径,直到遍历完整个图或树。
 DFS使用栈或递归来管理节点的遍历顺序,一般使用递归
很多时候DFS和回溯法不必过度区分。

排列树图解

子集树图解

回溯法模板

这是一个排列型搜索树,实际上的回溯法比较灵活,需要根据题意要求来具体分析。
vis[i]表示数字i是否使用过,也经常被用于表示某个元素是否使用过。
a[]存放结果,当dep深度=n+1时说明n层都已经算完了,直接输出结果。
子集型搜索树模板结构类似,就是在往下走时候只有两条边,表示“选或不选当前这个元素”。

例题讲解

(1)

首先可以肯定的是,每一行必然有且仅有一个皇后(因为不可能出现两个皇后在同一行),于是就通过枚举每一层皇后的位置来搜索所有可能解即可。
每放置一个皇后就将对应的米字型区域设置为“禁区”,后面的皇后就不能放在“禁区”里,回溯的时候将禁区取消掉。为了正确维护“禁区”,不能使用bool数组来表示禁区,需要使用int数组,表示这个位置被“多少个皇后占用了”,当占用数为0时表示“禁区解除”。
层数到n+1时表示找到了一个解,不可行的解都到不了第n+1层。

代码如下:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int n = 15;
int n, ans;
int vis[N][N];//表示被多少个皇后占用

void dfs(int dep)
{
  if(dep == n + 1)
{
  ans ++;
  return;
}

for(int i = 1; i <= n; ++ i)
{

   if(vis[dep][i])continue;
   for(int _i = 1; _i <= n; ++ _i)vis[_i][i] ++;
   for(int _i = dep; _j = i; _i >= 1 && _j >= 1; -- _i, -- _j)vis[_i][_j] ++;
   for(int _i = dep; _j = i; _i <= n && _j >= 1; ++ _i, -- _j)vis[_i][_j] ++;
   for(int _i = dep; _j = i; _i >= 1 && _j <= n; -- _i, ++ _j)vis[_i][_j] ++;
   for(int _i = dep; _j = i; _i <= n && _j <= n; ++ _i, ++ _j)vis[_i][_j] ++;

  dfs(dep + 1);

  for(int _i = 1; _i <= n; ++ _i)vis[_i][i] --;
  for(int _i = dep; _j = i; _i >= 1 && _j >= 1; -- _i, -- _j)vis[_i][_j] --;
  for(int _i = dep; _j = i; _i <= n && _j >= 1; ++ _i, -- _j)vis[_i][_j] --;
  for(int _i = dep; _j = i; _i >= 1 && _j <= n; -- _i, ++ _j)vis[_i][_j] --;
  for(int _i = dep; _j = i; _i <= n && _j <= n; ++ _i, ++ _j)vis[_i][_j] --;




int main()
{
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

  cin >> n;
  dfs(1);
  cout << ans << '\n';
  return 0;
}

(2)

跑dfs求最大的环,可以用时间戳 ( dfn ) ,将走过的地方标记一个时间戳(即第几步走到的)。
后续搜索中,每次开始时更新最小时间戳 ( mindfn ) ,如果走到已经走过的点就必须停下,然后根据时间戳的合法性来更新最大值。

代码如下:

(3)

先用dfs将不同的岛屿染上不同的颜色,然后计算最后剩下的岛屿的颜色有多少和原先总岛屿数(即颜色数)减去剩余颜色数,得到的就是淹没的岛屿数量。需要考虑的细节较多,自己多加理解

代码如下:

·剪枝

所谓剪枝

其实就是将搜索过程当中一些不必要的部分直接剔除掉,因为搜索过程构成了一棵树,刷除不必要的部分,就像是在树上将树枝剪掉,故名剪枝
剪枝是回测法的一种重要优化手段,方法往往先写一个暴力搜索,然后找到某些特殊的数学关系,或者逻辑关系,通过它们的约束让搜索树尽可能浅而小,从而达到降低时间复杂度的目的。
一般来说,剪枝的复杂度难以计算。

例题

lanqiao OJ 2942数字王国之军训排队


因为n比较小,所以我们可以从小到大枚举“最少队伍的数量”,然后再判断在这个队伍数量的情况下,是否可以成功分组。
这个判断合法性的函数就用搜索来实现,具体地来说,就是确定总队伍数量,然后对于每一个人,枚举他所属的队伍,用回溯法解决。
剪枝策略是,当某个人进入队伍时直接检查是否存在信系,如果存在就直接跳过。

错误展示(未剪枝):

正确代码修正:

lanqiao OJ 3008特殊的多边形

不妨规定我们构造出的3元组是递增的,那么在搜索过程中我们就可以通过计算得到当前这个位置的上限(剪枝的关键)。dfs过程中记录乘积,因为乘得越多数字越大,当乘积mul>1e6时直接返回(乘积很容易就超过1e5,数字较大时层数就两三层)。
同时还能记录一下 n - 1 条边的长度和sum,最后一条边必须小于sum。
最后用前缀和快速进行区间查询。

代码示例:

lanqiao OJ 3075特殊的多边形

不妨规定我们构造出的n元组是递增的,那么在搜索过程中我们就可以通过计算得到当前这个位置的上限(剪枝的关键)。dfs过程中记录乘积,因为乘得越多数字越大,当乘积mul>1e5时直接返回(乘积很容易就超过1e5,数字较大时层数就两三层)。
同时还能记录一下n-1条边的长度和sum,最后一条边必须小于sum
最后用前缀和快速进行区间查询。

代码示例:

·记忆化

所谓记忆化

就是将搜索过程中会重复计算且结果相同的部分保存下来,作为一个状态,下次访问到这个状态时直接将这个子搜索的结果返回,而不需要再重新算一遍。
通常会使用数组或map来进行记忆化,下标一般和dfs的参数表对应
注意使用记忆化需要保证重复计算的结果是相同的,否则可能产生数据失真

斐波那契数列

如果直接采用递归来做,时间复杂度将接近O(2^n),但是我们会发现有大部分的重复计算,比如F[n-2]在求F[n]的时候算过,在求F[n-1]的时候又被算了一次,而F[1]计算次数更多了,但它们在重复计算的时候的结果是相同的,所以可以采用记忆化(也叫带备忘录的搜索)。

第19行对dp进行初始化,初始化为-1,指这个状态还没有被算过;当dp[n]不是-1时说明之前已经被算过,可以返回 dp[n]

lanqiao OJ 3820 混境之地5

错误代码示例(没用记忆):
 

正确代码示例:

lanqiao OJ 216 地宫取宝

直接写搜索是会超时的,因为这个地图其实也不小了。首先进行一个条件转换:格子中的宝贝价值比手中任意宝贝价值都大=>格子中的宝贝价值大于手中宝贝价值的最大值。

我们记录这个最大值为mx,手中宝贝个数为cnt,于是就可以设置状态dp[x][y][mx][cnt]表示走到(x,y),手中有cnt个宝贝,且最大值为mx的方案数。

相关文章:

  • el-table折叠懒加载支持排序
  • -PHP 应用文件管理模块包含上传遍历写入删除下载安全
  • C++调用ffmpeg解复用、解码案例
  • vue学习九
  • Apache APISIX 架构浅析
  • 巧用输出变量,提升Dolphinscheduler工作流灵活性和可维护性
  • 【多线程-第四天-自己模拟SDWebImage的下载图片功能-自定义block和传递参数 Objective-C语言】
  • 技术引领未来创新发展引擎
  • 库存扣减解决方案
  • 南京审计大学:《 面向工程审计行业的DeepSeek大模型应用指南》.pdf(免费下载)
  • 7. 【Vue实战--孢子记账--Web 版开发】-- 收支分类设置
  • MySQL 调优:查询慢除了索引还能因为什么?
  • 设计模式之责任链模式:原理、实现与应用
  • 各软件快捷键
  • 【CXX-Qt】2.5 继承
  • 基于认证的 Harbor 容器镜像仓库
  • 基于koajsAdmin+mongodb的后台管理快速开发框架安装运行记录
  • 深度学习-151-Dify工具之创建一个生成财务报表的智能体Agent
  • 【容器运维】docker搭建私有仓库
  • 【MySQL篇】复合查询
  • 网站是如何建立的呢/昆明长尾词seo怎么优化
  • 做网站价格和配置/产品网络营销策划
  • 太仓企业网站建设价格/关联词有哪些四年级
  • nas做视频网站/百度app登录
  • 济南网站建设第六网建/网络营销和传统营销的区别和联系
  • 如何查看网站做没做竞价/烟台百度推广公司