蓝桥杯杯赛之深度优先搜索优化《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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字逻辑分析仪初体验

为啥会用到这玩意儿&#xff0c;要从一个荒诞的需求开始。想在市面上找一款特别低空飞行的监控&#xff0c;而且不想它一直开着监控&#xff0c;最好是我在外面远程指挥它起飞&#xff0c;飞去厨房&#xff0c;飞去洗手间&#xff0c;甚至飞去阳台&#xff0c;查看水龙头情况啊…

交错字符串

题目链接 交错字符串 题目描述 注意点 s1、s2、和 s3 都由小写英文字母组成0 < s1.length, s2.length < 1000 < s3.length < 200能否仅使用 O(s2.length) 额外的内存空间来解决它 解答思路 最初想到的是使用深度优先遍历&#xff0c;使用指针指向当前s3需要的…

【协议篇:Http与Https】

1. Http 1.1 Http的定义 超文本传输协议&#xff08;Hypertext Transfer Protocol&#xff0c;HTTP&#xff09;是用于分布式、协作式和超媒体信息系统的应用层协议。它是互联网上最广泛应用的数据通信协议之一&#xff0c;尤其对于万维网&#xff08;WWW&#xff09;服务而言…

如何使用PL/SQL Developer工具导出clob字段的表?

1 准备测试数据 导出测试对象&#xff1a;表test_0102&#xff0c;others字段为clob类型 --创建中间表test_0101 create table test_0101( id number, name varchar2(20), others clob);--插入100条测试数据 beginfor i in 1..100 loopinsert into test_0101 values(i,i||_a,l…

藏不住了!这20个技术点是运维老手的秘密武器

你们好&#xff0c;我的网工朋友。 信息技术系统的正常运行直接关系到企业或生产的正常运行。 然而&#xff0c;网工经常面临以下问题&#xff1a;网络速度慢、设备故障和应用系统效率低。 任何信息技术系统的故障&#xff0c;如果不及时处理&#xff0c;都会产生很大的影响…

【项目实战】【Docker】【Git】【Linux】部署V2rayA项目

今天着手了一个全新领域的项目&#xff0c;从完全没有头绪到成功运行&#xff0c;记录一下具体的部署流程 github项目链接V2rayA 一开始拿到以后完全没有抓手&#xff0c;去阅读了一下他的帮助文档 写着能用docker运行&#xff0c;就去下载了一个Docker配置了一下 拉取代码到…

frp内网穿透之(反向代理nginx)

通过公网 https 连接访问内网&#xff08;局域网&#xff09;本地http服务如下&#xff1a; 1.准备工作 ​ 想要实现内网穿透功能首先我们需要准备&#xff1a; 一台公网服务器&#xff08;用作frps的服务端&#xff09;一台需要做转发的内网服务器&#xff08;用作frpc的客…

求m和n的最大公约数(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int remainder 1;int m 0;int n 0;int middle 0;//提示用户&#xff1b;printf("请输入整数m和n的值&#xff…

在不同操作系统中搭建Python编程环境

1 在不同操作系统中搭建Python编程环境 1.1 在Linux系统中搭建Python编程环境 1. 检查Python版本 在你的系统中运行应用程序Terminal&#xff08;如果你使用的是Ubuntu&#xff0c;可按Ctrl Alt T&#xff09;&#xff0c;打开一个终端窗口。为确定是否安装了Python&…

医保是如何报销的

《医保是如何报销的》 这是罗师兄的原创文章 预计5-6分钟读完 作者&#xff1a;罗师兄 地球号&#xff1a;luoyun515 很多时候大家听到医保报销比例80%&#xff0c;85%&#xff0c;90%等&#xff0c; 但真正报销后&#xff0c; 实际花费跟报销额度根本达不到这么高&#…

宏的使用(C语言详解)

在写一个代码生成可执行文件的过程需要经过编译和链接&#xff0c;编译又要经过三部&#xff1a;预处理&#xff0c;编译&#xff0c;汇编。 #define定义的变量和宏就是在预处理阶段会处理的。 一个简单的宏定义&#xff1a; #include<stdio.h>; #define Max(a,b) a>…

《Java面试自救指南》(专题三)数据库

文章目录 一条sql语句的查询流程有哪些数据库存储引擎&#xff0c;各自的区别数据库的三大范式事务的四大特性&#xff08;含隔离级别&#xff09;MySQL四种隔离机制的底层实现&#xff08;如何解决幻读 &#xff09;MySQL有哪几种锁&#xff0c;分别怎么实现数据库中有哪些索引…