可后悔贪心 -- 解题报告

反悔贪心_Elicsyd的博客-CSDN博客

感觉普通贪心是每一个维度都是平等的,没有优先级。而可后悔贪心是存在某个维度是不可变的,不能直接用排序或者堆进行维护,常常需要经过某种处理,通过挖掘出题目中关于不可变维度的特殊性质,使其可以用排序或者堆等数据结构进行贪心。

可后悔贪心常用堆(priority_queue)进行维护。

[E. Buy Low Sell High](Problem - E - Codeforces)

问题描述:

您可以完美预测某只股票未来 N 天的价格。您想利用这一知识获利,但每天只想交易一股股票。也就是说,每天你要么买入一股,要么卖出一股,要么什么也不做。起初你拥有的股票为零,当你没有股票时,你不能卖出股票。在N天结束时,你希望再次拥有零股,但希望拥有尽可能多的资金。 — 插件 cf better 翻译

思路:这一题跟股票买卖差不多,但是这个是每次都是可以买/卖/不进行操作,而且对于买卖股票没有次数限制。直接贪心:i天买入,j天卖出,要求j天对于i来说是最大的,但是没有限制次数,这样贪心需要维护区间内的,可能需要用dp。

这题为什么会后悔:价格 a b c,a < b对于贪心来说要卖出,但是卖出后,到c发现a < b < c,即|c - a| 大于 |b - a|,这时会发现我们的贪心就错误了,应该在c再卖出。发现b - a + c - b == c - a,利用差值可以将局部最优转为全局最优。

具体代码思路:用一个小顶堆维护之前最小的价值,当当前价值大于之前最小的价值时可以卖出,pop后再将当前价值push到小顶堆中。之后在将当前价值push到小顶堆中,表示以当前价值为买入点的股票低点。

1 4 10 20为例,答案为25,是1 --> 10 4 --> 20 或者 1 --> 20 4 --> 10这样。

代码:

void solve() {int n; cin>>n;vector<int> a(n);for(auto &t: a) cin>>t;priority_queue<int, vector<int>, greater<int>> q;LL ans = 0;for(auto t: a) {if(q.size() && q.top() < t) {ans += t - q.top();q.pop();q.push(t);}q.push(t);}cout<<ans<<endl;
}

[P8769 [蓝桥杯 2021 国 C] 巧克力]([P8769 蓝桥杯 2021 国 C] 巧克力 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn))

问题描述:

小蓝很喜欢吃巧克力,他每天都要吃一块巧克力。

一天小蓝到超市想买一些巧克力。超市的货架上有很多种巧克力,每种巧克力有自己的价格、数量和剩余的保质期天数,小蓝只吃没过保质期的巧克力,请问小蓝最少花多少钱能买到让自己吃 x 天的巧克力。

思路:这题跟上一个类似,对abc按b进行排序,按b从大到小(从大到小如果后悔简单且一定是可以的)开始进行后悔贪心。与上题不同在于这题还有个数量c,上题没有。可以发现,满足条件只需要x个面包,且对于在i天而言,只要面包的保质期大于等于i,无脑选价钱最小的即可。因此可以按天数从结束天到开始天进行模拟,每次找没过保质期的最小价格的面包。

具体代码思路:用array<int,3>依次存入a b c,按b从大到小进行排序。用一个自定义小顶堆来维护对于遍历到i满足面包不过期的剩余面包的最小价格。每次找一个最小价格加入答案即可。

代码:

void solve() {int n,x; cin>>x>>n;vector<array<int,3>> va(n);for(auto &t:va) cin>>t[0]>>t[1]>>t[2]; // a b csort(all(va), [](array<int,3> pre, array<int,3> suf) {return pre[1] > suf[1];});auto cmp = [](PII pre, PII suf) {return pre.vf > suf.vf;};priority_queue<PII, vector<PII>, decltype(cmp)> maq(cmp);LL ans = 0;int pos = 0;for(int i = x; i >= 1; --i) {while(pos < n && va[pos][1] >= i) {maq.push({va[pos][0], va[pos][2]});pos++;}if(maq.size() == 0) {cout<<-1;return ;}auto tmp = maq.top(); maq.pop();ans += tmp.vf; tmp.vs--;if(tmp.vs != 0) {maq.push({tmp});}}cout<<ans;
}

[P4053 [JSOI2007] 建筑抢修]([P4053 JSOI2007] 建筑抢修 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn))

问题描述:

小刚在玩 JSOI 提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T 部落消灭了所有 Z 部落的入侵者。但是 T 部落的基地里已经有 �N 个建筑设施受到了严重的损伤,如果不尽快修复的话,这些建筑设施将会完全毁坏。现在的情况是:T 部落基地里只有一个修理工人,虽然他能瞬间到达任何一个建筑,但是修复每个建筑都需要一定的时间。同时,修理工人修理完一个建筑才能修理下一个建筑,不能同时修理多个建筑。如果某个建筑在一段时间之内没有完全修理完毕,这个建筑就报废了。你的任务是帮小刚合理的制订一个修理顺序,以抢修尽可能多的建筑。

思路:每一个建筑有一个最后截止时间和抢修耗时。对截止时间从小到大进行(原理同上)排序,用一个变量记录当前时间,如果当前时间加上维修时间在截止时间之内则可以,否则在前面可以的建筑中找一个最耗时的,如果那个最好时的大于当前耗时则进行替换,挤出点时间,为后面进行成功增加几率。

具体代码思路:用pair存入维护时间,截止时间。按截止时间进行升序排序。用一个变量lasttm记录当前进行到的时间,如果lasttm + vf <= vs表示这个建筑在截止前可以抢修成功则更新lasttm,并将维护时间vf放入到大顶堆中;如果不满足要求,表示这个建筑不可能被维修成功在截止时间之前,则在之前维修好的建筑中将一个维修时间较长的跟这个进行替代,lasttm更新,次数更新的lasttm一定比之前的未更新的lasttm要小。

代码:

void solve() {int n; cin>>n;vector<PII> vp(n);for(auto &t: vp) cin>>t.vf>>t.vs;sort(all(vp), [&](PII pre, PII suf) {return pre.vs < suf.vs;});int cnt = 0;int lasttm = 0;priority_queue<int> pq;for(int i = 0; i < n; ++i) {if(lasttm + vp[i].vf <= vp[i].vs) {cnt++;lasttm += vp[i].vf;pq.push(vp[i].vf);} else if(pq.top() > vp[i].vf) {lasttm -= pq.top(); pq.pop();lasttm += vp[i].vf; pq.push(vp[i].vf);}}cout<<cnt;
}

[tokitsukaze and Soldier](tokitsukaze and Soldier (nowcoder.com))

问题描述:

链接:https://ac.nowcoder.com/acm/problem/50439
来源:牛客网

在一个游戏中,tokitsukaze需要在n个士兵中选出一些士兵组成一个团去打副本。
第i个士兵的战力为v[i],团的战力是团内所有士兵的战力之和。
但是这些士兵有特殊的要求:如果选了第i个士兵,这个士兵希望团的人数不超过s[i]。(如果不选第i个士兵,就没有这个限制。)
tokitsukaze想知道,团的战力最大为多少。

思路:按特殊要求的不超过人数进行降序排,因为如果要求人数下降了,可以将之前进入的士兵无脑出队,而不用额外考虑其他信息。

具体代码思路:用pair依次存入战力和要求人数,按要求人数进行降序排序。用小顶堆维护满足要求人数限制条件的士兵的战力。对于第i个士兵,进入答案++,之后处理满足当前士兵要求的人数限制,如果有多余的则将战力最低的出队。每次遍历士兵时都取了max(因为可能中间要求得是最大战力之和,但是记录是遍历到的最后一个士兵时的最大战力之和。

代码:

void solve() {int n; cin>>n;vector<PII> vp(n);for(auto &t: vp) cin>>t.vf>>t.vs; // v s1sort(all(vp), [](PII pre, PII suf) {return pre.vs > suf.vs;});LL ans = 0;LL ma = -3;priority_queue<int,vector<int>,greater<int>> pq;for(auto t: vp) {ans += t.vf;pq.push(t.vf);while(pq.size() > t.vs) {ans -= pq.top(); pq.pop();}ma = max(ma, ans);}cout<<ma;
}

总结

可后悔贪心感觉用排序和堆完美的用上了题目中的性质,解决掉了普通贪心的不足。

发现是贪心 --> 常规贪心有点奇怪 --> 考虑可后悔贪心 / 换算法 / 再挣扎挣扎 --> 其他

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

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

相关文章

架构:C4 Model

概念 C4说穿了就是几个要素&#xff1a;关系——带箭头的线、元素——方块和角色、关系描述——线上的文字、元素的描述——方块和角色里的文字、元素的标记——方块和角色的颜色、虚线框&#xff08;在C4里面虚线框的表达力被极大的限制了&#xff0c;我觉得可以给虚线框更大…

A Mathematical Framework for Transformer Circuits—Part (1)

A Mathematical Framework for Transformer Circuits 前言Summary of ResultsREVERSE ENGINEERING RESULTSCONCEPTUAL TAKE-AWAYS Transformer OverviewModel SimplificationsHigh-Level ArchitectureVirtual Weights and the Residual Stream as a Communication ChannelVIRTU…

AWK语言第二版 1.2简单输出

1.2 简单输出 本章的后续部分&#xff0c;包含了一系列简单但典型的Awk程序样例&#xff0c;都是对前面的emp.data文件进行操作。为防遗忘&#xff0c;这里把emp.data文件再发一遍&#xff1a; Beth 21 0 Dan 19 0 Kathy 15.50 10 Mark 25 20 M…

Ubuntu18.04:ORB-SLAM3使用数据集构建地图和保存点云地图

文章目录 保存地图方法一&#xff1a;使用ORB-SLAM3自带的保存方法&#xff08;oea后缀文件&#xff09;保存地图方法二&#xff1a;使用PCL库保存为PCD类型地图文件安装PCL库&#xff1a;取巧方法&#xff1a;CMakeLists.txt 文件修改内容&#xff1a;&#xff08;向该文件内添…

常见的CSS定位技术及使用

目录 1.相对定位&#xff08;Relative Positioning&#xff09; 2.绝对定位&#xff08;Absolute Positioning&#xff09; 3.子绝父相 4.固定定位&#xff08;Fixed Positioning&#xff09; 5.粘性定位&#xff08;Sticky Positioning&#xff09; 6.弹性盒子布局&…

跳出Lambda表达式forEach()循环解决思路

背景 在一次需求开发时&#xff0c;发现使用Lambda的forEach()跳不出循环。如下示例代码&#xff0c;想在遍历满足条件时跳出循环。 public static void main(String[] args) {List<Integer> list Arrays.asList(1, 4, 5, 7, 9, 11);list.forEach(e -> {if (e % 2 …

ip route get ip地址 应用案例

应用场景 在做虚拟化实验用的虚拟机和实际的ECS云主机一般都会有多个网卡&#xff0c;网络的联通性是经常碰到的问题。比如在一个VM上有3个网卡&#xff0c;分别为ens160(和寄主机进行桥接的网卡10.0.0.128)、ens224&#xff08;连接仅主机网络10.0.0.0/24的网卡10.0.0.128&…

C++中几种处理函数返回值的方式

目录 C中几种处理函数返回值的方式&#xff1a;值返回引用返回指针返回总结 C中几种处理函数返回值的方式&#xff1a; 值返回 函数可以返回一个具体的值&#xff0c;例如整数、浮点数、结构体、类对象等。返回值被复制到函数调用点&#xff0c;在调用点可以直接使用或赋给其…

C语言面试题值反转字符串

知识捡漏本 1.C语言优先级 &#xff1a;左高于高于 右 2.定义宏函数product&#xff0c;调用product后&#xff0c;里面的i和i都是加两次1&#xff0c;i就是两个加2后的i相乘&#xff0c;i是开始的i和1后的i相乘。 3.用i (j4,k 8,m 16);这种定义方法&#xff0c;最终i和最后一…

2023最新Python重点知识万字汇总

这是一份来自于 SegmentFault 上的开发者 二十一 总结的 Python 重点。由于总结了太多的东西&#xff0c;所以篇幅有点长&#xff0c;这也是作者"缝缝补补"总结了好久的东西。 **Py2 VS Py3** * print成为了函数&#xff0c;python2是关键字* 不再有unicode对象…

AI图像行为分析算法 opencv

AI图像行为分析算法通过pythonopencv深度学习框架对现场操作行为进行全程实时分析&#xff0c;AI图像行为分析算法通过人工智能视觉能够准确判断出现场人员的作业行为是否符合SOP流程规定&#xff0c;并对违规操作行为进行自动抓拍告警。OpenCV是一个基于Apache2.0许可&#xf…

【Linux】多路IO转接问题-select

select&#xff1a; 首先设置一个lfd绑定服务端地址结构&#xff0c;用于监听新的连接。select函数调用&#xff0c;用于对整个fd数组进行监听&#xff0c;该数组最大限制1024&#xff0c;通过遍历&#xff0c;来确定是哪个fd有变化&#xff1a; 1.如果是lfd&#xff1a;那么可…

Python编程练习与解答 练习93:在终端窗口居中一个显示字符串

编写一个函数&#xff0c;以字符串s作为第一个参数&#xff0c;以窗口的字符宽度w作为第二个参数。函数将返回一个新字符串&#xff0c;其中包括所需的前导空格&#xff0c;以便在打印时新字符串s在窗口居中显示。新字符串的构造方法如下&#xff1a; 如果s的长度大于或等于窗口…

Python基础以及代码

Python基础以及代码 1.第一个代码如下&#xff1a; # 项目&#xff1a;第一个项目 # 作者&#xff1a;Adair # 开放时间&#xff1a; 2023/8/15 21:52print("Hello,world!!")如图所示&#xff1a; 2.数字的代码如下&#xff1a; # 项目&#xff1a;演示第一个项…

自然语言处理(六):词的相似性和类比任务

词的相似性和类比任务 在前面的章节中&#xff0c;我们在一个小的数据集上训练了一个word2vec模型&#xff0c;并使用它为一个输入词寻找语义相似的词。实际上&#xff0c;在大型语料库上预先训练的词向量可以应用于下游的自然语言处理任务&#xff0c;为了直观地演示大型语料…

Kubernetes技术--k8s核心技术 Secret

1.概述 Secret 解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者 Pod Spec中。Secret可以以 Volume 或者环境变量的方式使用。 作用 加密数据存储在/etc中,使得pod容器以挂载volume方式进行访问。在进行的数据存储中是以base64加密的方式…

C++ struct 笔记(超级详细)

今日碎碎念&#xff1a;我在学C语言时经常用到结构体struct&#xff0c;之后在写C程序时遇到在struct中定义构造函数和成员函数的情况&#xff0c;这在c语言中是从未遇到过的&#xff0c;觉得奇怪&#xff0c;想到之前并没有真正系统学习C里的struct&#xff0c;有必要今天详细…

leetcode - 360周赛

一&#xff0c;2833. 距离原点最远的点 这道题的意思是&#xff0c;遇到 "L" 向左走&#xff0c;遇到 "R" 向右走&#xff0c;遇到 "_" 左右都可以走&#xff0c;那么要想找到距离原点最远的点&#xff0c;就是在找 | "L" "R&qu…

P1093 [NOIP2007 普及组] 奖学金

题目描述 某小学最近得到了一笔赞助&#xff0c;打算拿出其中一部分为学习成绩优秀的前 5 5 5 名学生发奖学金。期末&#xff0c;每个学生都有 3 3 3 门课的成绩:语文、数学、英语。先按总分从高到低排序&#xff0c;如果两个同学总分相同&#xff0c;再按语文成绩从高到低排…

代码随想录 - Day31 - 回溯:组合问题

代码随想录 - Day31 - 回溯&#xff1a;组合问题 77. 组合 最容易想到的&#xff1a;k层for循环。 显然不能写那么多层for循环&#xff0c;所以该方法pass 使用回溯法&#xff1a; 用递归解决嵌套层数的问题 n相当于树的宽度&#xff0c;k相当于树的深度。 找到最深处的叶子节…