【c++入门(2)】贪心训练

本文通过解析田忌赛马和拼点游戏的问题,深入探讨了贪心策略的应用。首先介绍了如何利用贪心思想解决半价购买月饼的问题,接着分析了田忌赛马的三种比赛策略,以及在多种马匹情况下如何制定贪心策略。最后,文章将田忌赛马的思路应用于拼点游戏,展示了如何通过贪心策略求解游戏的最高分和最低分。
摘要由CSDN通过智能技术生成

这次的题都不是可以来套模板的,他只是说有一种贪心的思想,有的甚至单单只是一个用贪心思路写的枚举。通过几道题来看看它是什么样的:

中秋节快到了,Tom决定为他的N名魔法学徒每人买一盒月饼。
Tom带着学徒们来到月饼店,让学徒们挑选自己喜欢的月饼。
学徒们欢天喜地的开始挑选月饼,没过多久学徒们就选好了自己喜
爱的月饼。其中第i名学徒挑选的月饼每盒价格为P[i]元,另
外由于月饼的保质期很短,所以月饼店对于每种月饼只会生
产一盒样品放在店中展示,当客户挑选好月饼付完钱
后月饼店才会生产月饼。为了不让客户再多跑一趟,月
饼店还提供收费的送货上门服务。Tom和学徒们平时都
需要在山中修炼,每年只有一次的下山的机会,所以所
有学徒都选择了送货上门服务。月饼的种类不同,送货
上门的费用也不同,其中第i名学员挑选的月饼的送货
上门费用为S[i]元,Tom需要为第i个学员负担P[i]+S[i]元。
等到学徒们都挑选好以后,Tom来到收银台结账,Tom只带了M元钱,算完账以后他发现他可能无法负担所有学徒购买月饼和送货上门
的费用。于是Tom和老板讨价还价,最终老板同意小科可以挑
选一盒月饼,老板可以以半价出售这盒月饼,也就是说如
果Tom选择让第i个学徒选择的月饼半价,那么他只需要为
这盒月饼支付P[i]/2元的费用,但是送货上门的费用无
法减免,还是S[i]元。Tom想知道他的M元钱,最多可以
为多少名学徒购买到月饼(月饼的送货费用也需要Tom支付)。

如果不考虑半价,那么显然优先购买 “价格+运费”之和最低的月饼。
排序:为挑选方便,将所有学徒按照“价格+运费”从小到大排序。
枚举:由于半价月饼只能选一个,枚举半价购买的月饼进行购买,剩下的钱优先购买“价格+运费”之和最低的月饼,计算可以购买的月饼盒数。
模拟:设半价购买的月饼为𝑖,由于已经按照“价格+运费”从小到大排序,排除月饼𝑖,从1 → N枚举所有月饼,一边模拟购买,一边更新剩余的钱数,直到无法购买。
答案:枚举的所有半价方案中,可以购买到的最多月饼盒数就是问题的答案。
时间复杂度可行。
理清了思路,我们来看看代码:
在这里插入图片描述

在这里插入图片描述接下来是个很常见的贪心:田忌赛马。
齐国的大将军田忌喜欢赛马。他经常和齐王赛马。他和齐王都有三匹马:常规马,上级马,超级马。一共赛三局,每局的胜者可以从负者这里取得200银币。每匹马只能用一次。齐王的马好,同等级的马,齐王的总是比田忌的要好一点。于是每次和齐王赛马,田忌总会输600银币。
田忌很沮丧,直到他遇到了著名的军师――孙膑。田忌采用了孙膑的计策之后,三场比赛下来,轻松而优雅地赢了齐王200银币。这实在是个很简单的计策。由于齐王总是先出最好的马,再出次好的,所以田忌用常规马对齐王的超级马,用自己的超级马对齐王的上级马,用自己的上级马对齐王的常规马,以两胜一负的战绩赢得200银币。实在很简单。
现在如果有很多匹马该怎么办呢?现在我们就要用贪心来解决这个问题。
我们用贪心的策略来接一下这道题为方便描述,设田忌为a,齐王为b,问题目标希望a获得尽量多的银币。将a和b的马都按照从小到达排序,a[l1]表示a当前最慢的马,a[r1]表示a当前最快的马,b[l2]表示b当前最慢的马,b[r2]表示b当前最快的马。
① 如果a[r1] > b[r2] (a最快的马 > b最快的马),则:让a[r1]和b[r2]比赛,得200。因为a[r1] > b[r2]时,a[r1]可以胜过b的任何一匹马,此时和b的任何一匹马比赛都能赢,但是优先跟b最快的马比,可以让后面的比赛更轻松。
② 如果条件1不成立,但a l1 > b l2(a最慢的马>b最慢的马),则:让a[l1]和b[l2]比赛,得200。因为a[l1]>b[l2]时,a的任何一匹马都能胜b[l2],此时用a[l1]去和b[l2]比赛,可以为a方
保留力量,让后面的比赛更可能获胜。
③ 如果条件1和条件2都不成立,则:让a[l1]和b[r2]比赛(a最慢的马和b最快的马比赛)。因为如果条件1不成立,那么a的任何一匹马都赢不了b最快的马,同时条件2也不成立,
那么a最慢的马也不可能赢b的任何一匹马,此时用a最慢的马消耗b最快的马最优。
在情况3中,是否a[l1]( a最慢的马)就一定会败给b[r2]( b最快的马)?
不一定,也有可能打平,例如:a有3匹马分别是10 10 10,b也有3匹马,也是10, 10, 10。
此时条件1和条件2都不满足,但是a[l1]和b[r2]会打平。
对于情况3,如果a[l1] < b[r2],则a减200银币,如果a[l1] == b[r2],a的银币保持不变。

int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int</
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

{∞}

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值