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

蓝桥杯杯赛之深度优先搜索优化《1.分成互质组》 《 2.小猫爬山》【dfs】【深度搜索剪枝优化】【搜索顺序】

文章目录

  • 思想
  • 例题
    • 1. 分成互质组
      • 题目链接
      • 题目描述
      • 【解法一】
      • 【解法二】
    • 2. 小猫爬山
      • 题目链接
      • 题目描述
      • 输入样例:
      • 输出样例:
      • 【思路】
      • 【WA代码】
      • 【AC代码】

思想

  1. 本质为两种搜索顺序
  • 枚举当前元素可以放入哪一组
  • 枚举每一组可以放入哪些元素
  1. 操作为两种
  • 放入当前组
  • 新开一个组

例题

1. 分成互质组

题目链接

https://www.acwing.com/problem/content/1120/

题目描述

在这里插入图片描述

【解法一】

枚举每一组可以放哪些元素

#include <iostream>
using namespace std;
const int N = 11;
int g[N][N];
int a[N];
bool st[N];
int n;
int ans = N;
int gcd(int a, int b) {return b ? gcd(b, a % b) : a;
}
bool check(int g[], int x, int k) {for(int i = 0; i < k; i ++)if(gcd(g[i], x) > 1)	return false;return true;
}
void dfs(int gu, int gid, int start, int cnt) {if(gu >= ans)	return ;    //剪枝, 若当前分组大于答案,那么不如之前的也没必要枚举了if(cnt == n)	ans = min(ans, gu);bool flag = true;	//从start开始找,是否有元素不能入当前组for(int i = start; i < n; i ++) {if(!st[i] && check(g[gu], a[i], gid)) {st[i] = true;g[gu][gid] = a[i];dfs(gu, gid + 1, i + 1, cnt + 1);//恢复现场st[i] = false;flag = false; }} //操作二:新开数组if(flag) dfs(gu + 1, 0, 0, cnt);
}
int main() {cin >> n;for(int i = 0; i < n; i ++)	cin >> a[i];//当前在第几组,第几个数,从哪个位置开始选,已经选好几个数 dfs(1, 0, 0, 0);	cout << ans; return 0;
}

【解法二】

枚举当前元素可以放入哪个组

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;const int N = 10;
int a[N];
vector<int> g[N];   //互质组
int n;
int ans = N;int gcd(int a, int b){return b?gcd(b, a%b) : a;
}bool check(int c,int x){for(int i=0;i<g[c].size();i++){if(gcd(g[c][i],x)>1) return false;}return true;
}void dfs(int u, int k){ //当前为第u个数, 已开辟的组的个数if(u==n){ans=min(ans,k);return;}//每个元素的方法即 -> 放到当前已经存在的组中  或者  放到新开的组中//操作一:放入已经存在的组中for(int i=0; i < k; i ++){if(check(i, a[u])){g[i].push_back(a[u]);dfs(u + 1, k);g[i].pop_back();}}//可见这里的k代表着的是当前开辟数组的个数//操作二:新开一个组g[k].push_back(a[u]);dfs(u+1, k + 1);g[k].pop_back();
}int main(){cin>>n;for(int i=0;i<n;i++) cin>>a[i];dfs(0, 0);cout<<ans;return 0;
}

2. 小猫爬山

题目链接

https://www.acwing.com/problem/content/167/

题目描述

在这里插入图片描述

输入样例:

5 1996
1
2
1994
12
29

输出样例:

2

【思路】

第一步很容易会误以为这是一道背包问题,不过看了眼数据范围,容量太大,而n的范围很小,故为一道dfs搜搜问题

这里根据数据范围我们必然需要优化,分析可以优化的点:
在这里插入图片描述

  • ① 要求最小车辆,那么如果我们搜索某种决策时当前的车辆数已经大于ans了,那么必然不是最优解,直接退出即可
  • ② 对于dfs决策时,要想使得决策的分支少点,那么从根开始越少的话,那么必然分支也会更少,想到从此处进行优化的话,那么若是优先考虑重量大的,可以实现,因为在已有的车辆中选择可放入的重量大的可选车辆少

下面展示代码:

【WA代码】

在这里插入图片描述
枚举每一组可以放入哪些元素

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 20;
int n, W;
int w[N];
int g[N][N];
bool st[N];
int ans = N;void dfs(int gu, int ct, int start, int cnt) {if(gu >= ans)	return ;if(cnt == n) {ans = min(ans, gu);return;}bool flag = true;	//判断是否可以放进去当前组//操作一:加入当前组 for(int i = start; i < n; i ++) {if(!st[i] && ct + w[i] <= W) {st[i] = true;dfs(gu, ct + w[i], start + 1, cnt + 1);//恢复现场st[i] = false; flag = false;}}//操作二:新开组if(flag) 	dfs(gu + 1, 0, 0, cnt);}int main() {cin >> n >> W;for(int i = 0; i < n; i ++)	cin >> w[i];	//为了使得决策少点,优化时间,选择先放重量大的sort(w, w + n, greater<int>());//从第gu个组开始,当前在判断第gid个数,已经匹配的数字, 从哪个数开始 dfs(1, 0, 0, 0);cout << ans;return 0;
}

【AC代码】

枚举当前元素可以放入哪些组

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 20;
int n, W;
int w[N];
int sum[N]; //第i辆车的重量
bool st[N];
int ans = N;void dfs(int u, int k) {    //u代表当前遍历的数,k代表当前已有分组数量if(k >= ans)    return;if(u == n)  {// ans = min(ans, k);   //因为有上步条件制约,故不需要minans = k;return;}   //操作一:放入某个已有的车辆for(int i = 0; i < k; i ++) {if(sum[i] + w[u] <= W) {sum[i] += w[u];dfs(u + 1, k);//恢复现场sum[i] -= w[u];}}//操作二: 放不下,新开车辆sum[k] = w[u];dfs(u + 1, k + 1);sum[k] = 0;}int main() {cin >> n >> W;for(int i = 0; i < n; i ++)	cin >> w[i];	//为了使得决策少点,优化时间,选择先放重量大的sort(w, w + n, greater<int>());dfs(0, 0);cout << ans;return 0;
}

相关文章:

  • ZKP价值链路的垂直整合
  • Meta Pixel:助你实现高效地Facebook广告追踪
  • 【Figma】安装指南及基础操作
  • Unity Toggle组件
  • Tcl学习笔记(二)——表达式、字符串
  • vue快速入门(七)内联语句
  • VMware虚拟机(Rocky9.3)硬盘扩容详细图文教程
  • #{} 和 ${}区别
  • 算法刷题Day27 | 39. 组合总和、40.组合总和II、131.分割回文串
  • FastGpt流程
  • Redis 持久化个人总结
  • 【算法】两数之和(暴力求解+哈希表)
  • 用tkinter来实现扫雷游戏
  • usb_camera传输视频流编码的问题记录!
  • Elasticsearch 聚合函数返回空数组|查询返回空内容 rs里有数据
  • [NodeJS] 关于Buffer
  • 【跃迁之路】【463天】刻意练习系列222(2018.05.14)
  • const let
  • js 实现textarea输入字数提示
  • LeetCode算法系列_0891_子序列宽度之和
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • Node项目之评分系统(二)- 数据库设计
  • PV统计优化设计
  • Shell编程
  • Sublime text 3 3103 注册码
  • Vue小说阅读器(仿追书神器)
  • 百度小程序遇到的问题
  • 动态魔术使用DBMS_SQL
  • 机器学习中为什么要做归一化normalization
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 前言-如何学习区块链
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 移动端唤起键盘时取消position:fixed定位
  • 找一份好的前端工作,起点很重要
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • ​ 全球云科技基础设施:亚马逊云科技的海外服务器网络如何演进
  • # .NET Framework中使用命名管道进行进程间通信
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • ###项目技术发展史
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程
  • (最优化理论与方法)第二章最优化所需基础知识-第三节:重要凸集举例
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .NET Core MongoDB数据仓储和工作单元模式封装
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .net 调用php,php 调用.net com组件 --
  • .Net小白的大学四年,内含面经
  • .net之微信企业号开发(一) 所使用的环境与工具以及准备工作
  • @FeignClient注解,fallback和fallbackFactory
  • [04] Android逐帧动画(一)
  • [Android]RecyclerView添加HeaderView出现宽度问题
  • [AutoSAR系列] 1.3 AutoSar 架构
  • [BIZ] - 1.金融交易系统特点
  • [iOS]随机生成UUID通用唯一识别码