贪心专题探讨
导言
有人说,在古代以及近代,维护信任的纽带大多是道德与名誉。而到了现代,只有利益才能够稳定地维护信任。但其实,道德与名誉在古时显然也是一种利益。道德带来信誉,良好的信誉是邻里关系的基础,这是社交环境中最大的利益。人们拥有不同理智程度的价值观,以自己的价值观为准绳,去进行利益最大化,也就是所谓的贪心。而为了最大化特定群体的利益,统治者需要规范人们的价值观,于是意识形态便出现了。
许多人利益最大化的首要受众一般是自我个人或代表自我的一个小团体或神,因此产生了奴隶、封建、神权等意识形态。而后受众逐渐变成“人们”、“人民”,例如资本主义 (CAPITALISM) 认为每个人贪心的受众是自己的财产、共产主义 (COMMUNISM) 认为每个人贪心的受众是群体。意识形态是强加给受众的价值观,现代以绝大部分人为利益受众的价值观都是历史上伟大的思想家为了改进人们普遍不理智的价值观而做出的实践。这些意识形态是为了让人们拥有更理智的贪心观,从而使社会能创造更多利益。
因此,无论古今,无论中外,各种不同的意识形态告诉我们,人们都是贪心的。
南辕北辙的故事告诉我们,贪心的正确度不同,就决定了这条道路是明亮还是晦暗。在如今的美国,无论怎么走,走的都是下坡路。而在正确的思想指引下,无论怎么走都有上坡路。所以在这一章节中,让我们通过一些例子来研习并口头探讨什么才是正确的贪心。
通法:
1. 考虑朴素的 dp 方法来获得启发
2. 按某种顺序考虑所有选项
3. 以某种比较方法尝试替换之前的某个选项
某种顺序:
通常指按限制的严格程度由严到宽
某种比较方法
通常指交换后是否能使答案不劣
某个选项
通常指占用/花费最大的选项
另法:
如果能确定 "选择了
P2949 [USACO09OPEN] Work Scheduling G
从
时刻开始,有 个单位时间。在任一时刻,他都可以选择编号 到 的 项工作中的任意一项工作来完成。 每个单位时间里只能做一个工作。 对于第 个工作,有一个截止时间 ,如果他可以完成这个工作,那么他可以获利 . 在给定的工作利润和截止时间下,约翰能够获得的利润最大为多少.
某种顺序:截止时间由小到大
某种比较方法:利润大小
某个选项:利润最小的选项
P1650 田忌赛马
齐王和田忌各有
匹马,每个马有速度值 ,
某种顺序:田忌马的速度
某种比较方法:是否能赢
某个选项:任意一头没被匹配的齐王的马
把两人马的速度分别从大到小排序。最优答案显然是速度最快的几匹马赢,所以每匹田忌的马都去匹配还未匹配到的速度小于该马的速度最快的马,如果匹配不到,就结束循环,输出答案。
[JSOI2007] 建筑抢修
个建筑需要抢修,每个建筑抢修耗时为 , 如果没有在 之前抢修,建筑就报废。问最多能抢修多少个建筑。
, 。
考虑 dp :
式子:
sort([t1,t2]) => (t2[i] <= t2[i+1]);
fi(1,n){
for(int t=t2[i];t>=t1[i];--t)
f[t]=max(f[t],f[t-t1[i]]+1);
ff(t,1,t2[i])
f[t]=max(f[t],f[t-1]);
}
ans=f[t2[n]];
我们发现如果
某种顺序:截止时限由小到大
某种比较方法:报废是否是必要的
某个选项:耗时最大的建筑
如果在考虑某个建筑的时候,发现必须要报废一个了,那就把耗时最大的建筑(包括自己也考虑在内)给放弃掉。
P2107 小Z的AK计划
数轴上
个给定的点分别代表一道题,每个点坐标为 ,需要花费 的时间才能解决这道题。小 Z 移动一格消耗时间 ,初始在 。问 时间以内能解决多少题。
某种顺序:
某种比较方法:能否让解决题目数量不减的情况下让时间最短。
某个选项:
代码:https://www.luogu.com.cn/paste/inuywjby
这道题的选项好像没有什么限制,所以还可以这样贪:
某种顺序:
某种比较方法:能否让解决题目数量不减的情况下让时间最短。
某个选项:
这样做的话答案就要在枚举每道"必须做的题目"时更新。
CF865D Buy Low Sell High
天,第 天股价为 ,每天只能买卖共一股。求最大盈利。持股数量不能为负。
没有明显思路,考虑 dp:
选项也没有明显限制,因此我们按照天数贪。
可以发现卖出最低价应该比买入最高价高。也就说有一个界限值,这个值以上的尽量卖,以下的尽量买。
每个新的一天都先卖这个股票,并在之前没有卖的股票里面选最大的一个买。
某种顺序:
某种比较方法:所考卖出项是否在界限值以上,是否比
某个选项:
代码链接:https://www.luogu.com.cn/paste/yqx63eqs
顺带一提,这道题的题解代码和 CF13C Sequence 的题解代码如出一辙。有理由怀疑 CF13C 也可以贪心。
本题(代码中将 sell 和 unused 合并成了 q ,也就是所有可以被买进的项):
ll ans;
int a,n;
priority_queue<int,vector<int>,greater<int>>q;
int main(){
scanf("%d",&n);
fi(1,n){
scanf("%d",&a);
q.push(a);
if(a>q.top()){
ans+=a-q.top();
q.pop();
q.push(a);
}
}
printf("%lld\n",ans);
return 0;
}
CF13C:
ll ans;
int a,n;
priority_queue<int>q;
int main(){
scanf("%d",&n);
fi(1,n){
scanf("%d",&a);
q.push(a);
if(a<q.top()){
ans+=q.top()-a;
q.pop();
q.push(a);
}
}
printf("%lld\n",ans);
return 0;
}
P3545 [POI2012] HUR-Warehouse Store
现在有
天。第 天上午会进货 件商品,中午的时候会有顾客需要购买 件商品,可以选择满足顾客的要求,或是无视掉他。 如果要满足顾客的需求,就必须要有足够的库存。问最多能够满足多少个顾客的需求。
, 。
某种顺序:时间顺序
某种比较方法:是否能让剩余商品变多(也就是所考项的
某个选项:
代码链接:https://www.luogu.com.cn/record/188550301
P1484 种树
给定
。 个坑位可以种树。树不能相邻。你最多种 棵。在 位置种树的收益是
记录状态
-
最大 -
最小
的一个。以下省略
那么如果
否则如果
我猜测在
写个代码验证一下猜想。
啊哦,是错的。 7 3 \n 1 2 1 0 1 0 1
能够 hack 掉。
正确做法:按
代码链接:https://www.luogu.com.cn/record/189904358
CF730I Olympiad in Programming and Sports
个人,每个人两个属性 。给定 ,选出 个人获得其 ,选出 个人获得其 。求最大总获得。
旁边巨佬的思路:
任选
代码链接:https://codeforces.com/contest/730/submission/292473190
[AGC018C] Coins
个人,每个人三个属性 。给定 ,保证 ,选出 个人获得其 ,选出 个人获得其 ,选出 个人获得其 。求最大总获得。
既然保证了
问题就转化成了选
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现