蓝桥杯2023年省A(一波三折的)【买瓜】折半搜索+剪枝+排序

题目:洛谷 P9234 [蓝桥杯 2023 省 A] 买瓜


折半搜索

一开始觉得像dp,试着写了,显然过不了,但我实在觉得搜索也过不了啊,去看题解,发现使用了折半搜索(每天都觉得啥都不会捏
折半搜索就是先搜一半,记录下答案,再搜一半,最后把答案整合在一起
比如这题,每个数有三种选法,复杂度3n,折半后就是2*3n/2,大大降低了
但是这个复杂度还是过不了,后面就是不停优化剪枝

剪枝
剪枝1

当前和已经超过m (sum > m)

剪枝2

当前劈瓜次数已经超过历史最优 (k >= ans)

剪枝3

达到同样的和,曾经有过劈瓜数更小的方案 (mp.count(sum) && mp[sum] < k)

折半+剪枝(76分)
用unordered_map更快

#include <vector>
#include <iostream>
#include <cstdio>
#include <map> 
#include <unordered_map>
#include <ctime> 
using namespace std;typedef long long ll;
const int N = 35;ll a[N];
int ans = N;
unordered_map<ll, int> mp;//unordered_map更快
ll n, m;void dfs1(int i, int k, ll sum)
{if (sum > m) return;//超了,剪if (k >= ans) return;if (sum == m)//到了,走了{ans = min(ans, k);return; }if (mp.count(sum) && mp[sum] < k) return;//有过更优情况,剪!if (i > n / 2)//到头了,把搜到的东西记一下{//用map记录达到sum的砍刀数最小值if (mp.count(sum)) mp[sum] = min(mp[sum], k);else mp[sum] = k;return;}//先搜贡献大的更容易找到答案(大概吧dfs1(i + 1, k, sum + a[i] + a[i]);//整个dfs1(i + 1, k + 1, sum + a[i]);//半个dfs1(i + 1, k, sum); //不要
}void dfs2(int i, int k, ll sum)
{if (sum > m) return;if (k >= ans) return;if (sum == m){ans = min(ans, k);return; }if (i > n){//如果另一半有匹配的就更新答案if (mp.count(m - sum)) ans = min(ans, k + mp[m - sum]);return;}dfs2(i + 1, k, sum + a[i] + a[i]);dfs2(i + 1, k + 1, sum + a[i]);dfs2(i + 1, k, sum); 
}
int main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);cin >> n >> m;m += m;//为了不出现小数,把a[i]当半个瓜用,那么m也要翻倍for (int i = 1; i <= n; i++){cin >> a[i];}dfs1(1, 0, 0);dfs2(n/2+1, 0, 0);if (ans == N) cout << -1;else cout << ans;return 0;
}

继续看题解,发现很重要的一点是要给数组排序
为什么呢,不知道,大家都不说
好像挺有道理的但是我说不出道理,先放着

加上sort之后A了


觉得自己无敌了吧?来看看这个
题目 3145: 蓝桥杯2023年第十四届省赛真题-买瓜
欸~一模一样的代码只有82分
最后是怎么过的呢,要把数组从大到小排序
为什么呢
我的理解是,在搜第二段的时候,前面已经出现很多凑到m的情况,使ans变小了,所以第二段会被剪得更狠;相比之下第一段则几乎都要搜到头,所以重点在于要把第一段剪了。那有没有办法让第一段多剪掉一点呢,就让第一段都是大数,sum容易超过m,就会多多被剪了

加上从大到小排序:

sort(a + 1, a + n + 1, greater<int>()); 

正当我欢天喜地地准备结束这题的时候,我手欠地把从大到小版交到了洛谷
嘿——您猜怎么着?TLE了!
好吧我前边都是一顿瞎说(但我真是觉得有道理啊)
那只能是数据问题了,但是数据问题要怎么A啊!

剪枝4

后面我又翻看题解,发现了一个新的剪枝:
预处理后缀和,当前sum加上后缀和也够不到m的话就直接剪
注意这个剪枝只能在第一段中使用,因为第二段本身就要匹配第一段的答案,没法判断会不会不够

void dfs1(int i, int k, ll sum)
{if (sum > m) return;if (k >= ans) return;if (sum + suf[i] < m) return;//注意第i个还没加过,所以是判断sum + suf[i]if (sum == m){ans = min(ans, k);return; }if (i > n / 2){if (mp.count(sum)) mp[sum] = min(mp[sum], k);else mp[sum] = k;return;}dfs1(i + 1, k, sum + a[i] + a[i]);dfs1(i + 1, k + 1, sum + a[i]);dfs1(i + 1, k, sum); 
}

还有个注意点,要sort之后再算后缀和(对就是我这么傻
以及因为我存的a[i]算半个瓜,算后缀和要算整个瓜,所以要加两次

sort(a + 1, a + n + 1, greater<int>()); suf[n + 1] = 0;for (int i = n; i >= 1; i--){suf[i] = suf[i + 1] + a[i] + a[i];}

贴一个两边都能A的代码

#include <vector>
#include <iostream>
#include <cstdio>
#include <map> 
#include <unordered_map>
#include <ctime> 
#include <algorithm>
using namespace std;typedef long long ll;
const int N = 35;ll a[N], suf[N];
int ans = N;
unordered_map<ll, int> mp;
ll n, m;void dfs1(int i, int k, ll sum)
{if (sum > m) return;//超了,剪if (k >= ans) return;if (sum + suf[i] < m) return;//注意第i个还没加过,所以是判断sum + suf[i]if (sum == m)//到了,走了{ans = min(ans, k);return; }if (mp.count(sum) && mp[sum] < k) return;//有过更优情况,剪!if (i > n / 2)//到头了,把搜到的东西记一下{//用map记录达到sum的劈瓜数最小值if (mp.count(sum)) mp[sum] = min(mp[sum], k);else mp[sum] = k;return;}//先搜贡献大的更容易找到答案(大概吧dfs1(i + 1, k, sum + a[i] + a[i]);//整个dfs1(i + 1, k + 1, sum + a[i]);//半个dfs1(i + 1, k, sum); //不要
}void dfs2(int i, int k, ll sum)
{if (sum > m) return;if (k >= ans) return;if (sum == m){ans = min(ans, k);return; }if (i > n){//如果另一半有匹配的就更新答案if (mp.count(m - sum)) ans = min(ans, k + mp[m - sum]);return;}dfs2(i + 1, k, sum + a[i] + a[i]);dfs2(i + 1, k + 1, sum + a[i]);dfs2(i + 1, k, sum); 
}
int main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);cin >> n >> m;m += m;//为了不出现小数,把a[i]当半个瓜用,那么m也要翻倍for (int i = 1; i <= n; i++){cin >> a[i];}//sort(a + 1, a + n + 1); sort(a + 1, a + n + 1, greater<int>()); suf[n + 1] = 0;for (int i = n; i >= 1; i--){suf[i] = suf[i + 1] + a[i] + a[i];}dfs1(1, 0, 0);dfs2(n/2+1, 0, 0);if (ans == N) cout << -1;else cout << ans;return 0;
}

结果就是加上这个剪枝从大到小排序洛谷能过了,但是从小到大c语言网不行,继续看!


其他优化

我就不写了感觉好麻烦要把之前写的推翻重来orz

二分

不直接搜i+1,而是根据还需要的斤数在剩下的瓜里二分(因为已经排序了嘛),大于还需要的斤数的瓜可以不用考虑
(这样二分甚至可以不用折半搜索
见 P9234 [蓝桥杯 2023 省 A] 买瓜 题解

手写哈希表

大概是因为unordered_map还是常数大了吧(
见 买瓜 题解


参考

P9234 [蓝桥杯 2023 省 A] 买瓜 题解
买瓜 题解
买瓜题解


菜死我算了,真在赛场上碰到这种题我就拿个30分吧(默哀

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

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

相关文章

wayland(xdg_wm_base) + egl + opengles 渲染使用纹理贴图的旋转 3D 立方体实例(十三)

文章目录 前言一、使用 stb_image 库加载纹理图片1. 获取 stb_image.h 头文件2. 使用 stb_image.h 中的相关接口加载纹理图片3. 纹理图片——cordeBouee4.jpg二、渲染使用纹理贴图的旋转 3D 立方体1. egl_wayland_texture_cube.c2. Matrix.h 和 Matrix.c3. xdg-shell-client-pr…

日期与时间(Java)

文章目录 日期与时间&#xff08;Java&#xff09;一、JDK8之前的1.1 Date1.2 SimpleDateFormat1.3 Calendar 二、 JDK8之后的2.1 LocalDate、LocalTime和LocalDateTime2.2 ZoneId和ZonedDateTime2.3 Instant2.4 DateTimeFormatter2.4 Period和 Duration &#x1f389;写在最后…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Web)下篇

onRequestSelected onRequestSelected(callback: () > void) 当Web组件获得焦点时触发该回调。 示例&#xff1a; // xxx.ets import web_webview from ohos.web.webviewEntry Component struct WebComponent {controller: web_webview.WebviewController new web_webv…

Github Copilot 工具,无需账号,一键激活

① 无需账号&#xff0c;100%认证成功&#xff01;0风险&#xff0c;可联网可更新&#xff0c;&#xff0c;支持copilot版本升级&#xff0c;支持chat ② 支持windows、mac、linux系统等设备 ③一号通用&#xff0c;支持所有IDE(AppCode,CLion,DataGrip,GoLand,IntelliJ IDEA …

Linux 基础-查看和设置环境变量

一&#xff0c;查看环境变量 在 Linux中&#xff0c;环境变量是一个很重要的概念。环境变量可以由系统、用户、Shell 以及其他程序来设定&#xff0c;其是保存在变量 PATH 中。环境变量是一个可以被赋值的字符串&#xff0c;赋值范围包括数字、文本、文件名、设备以及其他类型…

前端跨平台开发框架:简化多端开发的利器

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

OpenCV系列文章目录(持续更新中......)

引言&#xff1a; OpenCV是一个开源的计算机视觉库&#xff0c;由英特尔公司开发并开源的一组跨平台的C函数和少量的C函数组成&#xff0c;用于实时图像处理、计算机视觉和机器学习等应用领域。OpenCV可以在包括Windows、Linux、macOS等各种操作系统平台上使用&#xff0c;具…

用Origin快速拟合荧光寿命、PL Decay (TRPL)数据分析处理

需要准备材料&#xff1a;Origin、PL Decay数据txt文件 首先打开Origin画图软件 导入数据&#xff0c;按照下图箭头操作直接导入 双击你要导入的PL Decay的txt数据文件&#xff0c;然后点OK 继续点OK 数据导入后首先删除最大光子数之前的无效数据&#xff0c;分析的时候用…

计算机设计大赛 题目:基于机器视觉opencv的手势检测 手势识别 算法 - 深度学习 卷积神经网络 opencv python

文章目录 1 简介2 传统机器视觉的手势检测2.1 轮廓检测法2.2 算法结果2.3 整体代码实现2.3.1 算法流程 3 深度学习方法做手势识别3.1 经典的卷积神经网络3.2 YOLO系列3.3 SSD3.4 实现步骤3.4.1 数据集3.4.2 图像预处理3.4.3 构建卷积神经网络结构3.4.4 实验训练过程及结果 3.5 …

特殊内齿轮加工的另一种选择

内齿轮加工普遍采用插齿或拉削&#xff0c;但对于一些特殊齿廓的内齿轮来说&#xff0c;插齿可能会有一定的困难&#xff0c;或者成本较高。在这种情况下&#xff0c;线切割加工不失为一种不错的选择。那么什么样的零件需要选择这种加工方式呢&#xff1f;一起来看看&#xff1…

Mr-Robot1靶场练习靶场推荐小白入门练习靶场渗透靶场bp爆破wordpress

下载链接&#xff1a; Mr-Robot: 1 ~ VulnHub 安装&#xff1a; 打开vxbox&#xff0c;菜单栏----管理----导入虚拟电脑 选择下载完的ova文件&#xff0c;并修改想要保存的位置&#xff08;也可以保持默认位置&#xff09; 导入完成后可以根据自己的情况去配置网络链接方式 完成…

数学建模--MATLAB基本使用

1.线性方程组 这个是一个线性方程组&#xff08;属于线性代数的范畴&#xff09;&#xff0c;Axb类型的方程&#xff0c;如果使用MATLAB进行求解&#xff0c;就需要分别表示A矩阵&#xff08;线性方程组未知数前面的系数&#xff09;&#xff0c;b矩阵&#xff08;表示等式右边…

大数据-基础架构设施演进的过程

一、第一阶段-Hadoop 以Hadoop为代表的离线数据处理基础设施 1.1、围绕HDFS和MR&#xff0c;产生了一系列的组件 面向在线KV操作的HBase面向SQL的Hive面向工作流的PIG 1.2、随着对批处理性能要求越来越高&#xff0c;产生了Tez、Spark、Flink等计算引擎。RM模型也逐步进化成…

SpringAI——Java生态接入LLM

最近&#xff0c;Spring官网发布了SpringAI&#xff0c;可点此查看https://spring.io/blog/2024/03/12/spring-ai-0-8-1-released&#xff0c;对于SpringAI的介绍&#xff0c;可看官方文档&#xff1a;https://spring.io/projects/spring-ai#overview。 本文将使用SpringAI配合…

字符函数以及字符串函数

1.strlen的使用和模拟实现 • 字符串以 \0 作为结束标志&#xff0c;strlen函数返回的是在字符串中 \0 前⾯出现的字符个数&#xff08;不包 含 \0 )。 • 参数指向的字符串必须要以 \0 结束。 • 注意函数的返回值为size_t&#xff0c;是⽆符号的&#xff08; 易错 &#xff…

Python之requests实现github模拟登录

文章目录 github 模拟登录前言模拟登录流程抓包操作查看登录表单的内容登录操作 模拟登录操作在 main函数的调用获得 auth_token调用/session接口登录处理检测登录是否成功 总结&#xff1a; github 模拟登录 前言 前面学习了requests模块的基础学习后&#xff0c;接下来做一个…

Pytorch学习 day14(模型的验证步骤)

如何利用已经训练好的模型&#xff0c;验证它的结果&#xff0c;步骤如下&#xff1a; 步骤一&#xff1a;加载测试输入并更改为合适尺寸 保存图片到指定文件夹下&#xff0c;注意是否为同级目录注意&#xff1a;返回上一级目录为“…/xxx"有时&#xff0c;我们自己的输…

前端React篇之React的生命周期有哪些?

目录 React的生命周期有哪些&#xff1f;挂载阶段&#xff08;Mounting&#xff09;更新阶段&#xff08;Updating&#xff09;卸载阶段&#xff08;Unmounting&#xff09;错误处理阶段&#xff08;Error Handling&#xff09; React常见的生命周期React主要生命周期 React的生…

27-Java MVC 模式

Java空对象模式 实现范例 MVC模式代表 Model-View-Controller&#xff08;模型-视图-控制器&#xff09; 模式MVC模式用于应用程序的分层开发 Model&#xff08;模型&#xff09; - 模型代表一个存取数据的对象或 JAVA POJO 它也可以带有逻辑&#xff0c;在数据变化时更新控制…

Ubuntu 如何安装 Beyond Compare?

Ubuntu20.04安装Beyond Compare 4.3.7 一、官网下载方式一&#xff1a;方法二&#xff1a;使用 .deb 包安装 二、安装相关依赖和bcompare三、破解常见错误解决方法 ) 文件比较工具Beyond Compare是一套由Scooter Software推出的文件比较工具。主要用途是对比两个文件夹或者文件…