Acm学习第三周

本文通过五个典型题型详细解析了贪心算法在解决区间重叠、截止日期、求最值、平均分配和性价比问题中的应用策略。通过对问题的深入分析,阐述了如何根据题意选择排序方式,优化解题过程,以求得最优解。同时,介绍了两道特殊问题的解决方法,展示了贪心算法在实际问题中的灵活性。
摘要由CSDN通过智能技术生成

贪心算法(Vjudge类型题分析)

以下题目分析,主要是写给自己看的,帮助自己理清思路

第一类:区间重叠

一般区间重叠的问题,都会有一个标志,就是给了你一段起始和终止数,然后根据题意判断它想要的是重叠部分还是不重叠部分,通常带区间的问题,在求解之前一定会有个排序,排序分为对起始时间排序和对终止时间排序,我们可以根据题意选择,比如如果所求的部分以每个区间的尾部为主则右排,否则左排。
以下两道例题主要是右排序,在D中,则是一个明显的左排问题,因为要要用木板铺泥潭,肯定是从泥潭的第一个位置坐标开始逐一往后铺,而不可能从每一个泥潭的末尾置倒着铺。

K
题目大意:已知每个节目的起始和终止时间,要使得所能观看的节目尽量多。
分析:如果想要看完第一个节目可以看第二个,那么必须保证第一个节目的终止时间小于等于第二个节目的起始时间,以此为条件我们可以设想,如果第一个节目的终止时间比第二个节目的起始时间大会怎么样?那么这表明,我们无法顺次观看第二个节目,于是可以继续将第一个节目的终止时间和第三个节目的起始时间比较,以此类推。
于是,我们可以得出此题的排序方式,即按照每个节目的终止时间由小到大排序。

T
题目大意:已知几个区间,要构造一个集合,该集合的元素都存在于所给的区间中,并且每段区间中都至少有两个整数属于该集合,让你求出构成该集合的最少的元素数目。
分析:如果使元素个数最少,并且满足每个区间都至少有两个整数属于该集合,则实质上,就是找区间的重叠部分。如果区间1和区间2重叠,并且使重叠部分只有两个元素(因为每个区间最少有两个元素属于该集合),则重叠部分的元素为两个区间共有,将这两个元素并入集合中,则可使集合中的元素最少。如果区间不止两个,有N个区间的话,那么如果可以使N个区间都重叠,并且只重叠两个整数,则该集合中的元素,就是仅有的N个区间重叠的两个元素。可事实上,N个区间一般是不会都完全重叠的,这个时候我们就需要进行比较,而如何更快更有效的比较出合适的重叠区间,这时我们需要引入一个排序:按照区间末尾置从小到大排序。
排序工作已经做好,第二步:因为每个区间至少两个整数属于该集合,则我们就可以在每个区间中取两个元素,而又因为如果使整体元素数目最少,所取元素可以与其它区间重叠会节省元素数目,因此最优的选择就是找区间的倒数第一n和倒数第二个元素m,定义一个新的小区间[m,n],将第二个区间的前两个元素x,y与m,n比较,比较情况分为:1.n<x 2.m<x&&x<=n 3.y<=m
根据每个情况,进行元素总数的++。

第二类:截止日期

一般做此类题时,我会先对贪心的主要对象进行排序,然后定义一个bool类型的变量,用来标记元素。将元素排序后,用一层循环进行遍历,遍历的同时,用另一层循环来查找该元素的期限,若此期限没有被标记,则说明可取,并标记改天,若期限被标记了,则再从前查找,如过查找不到没有被标记的时间,则说明在它的期限中有比它更优的元素。

J
题目大意:有N份作业,每一份作业都有相应的截止日期和分数,如果在截至时为完成作业,就把分数扣掉,我们的目的是找出扣除的最少分。
分析:本题的贪心主要目的是扣除分数最少,按照贪心原则,我们从分数出发即可,因此在排序中按照分数由高到低的方法排序,如果分数相同就按照截至日期由小到大排序,从排序中可以看出,如果想要在有限的时间内扣除分数最少,那么就要保证分数多的作业尽可能先做完。

第三类:求最值

其实贪心中的题有很多求某个情况下的最大最小值,为什么单独把它列出来呢,因为以往的题,在遍历元素时都要进行一个sort排序操作,而以下的题不需要,它们只需遍历的过程中,逐一比较即可,可以直接找到一个最值,而不需要排序标记等操作。

P
题目大意:查理喜欢跟随别的骑手一起,来避免独自骑马,查理要找跟他去一个地方的骑手,如果有更快的人超过了他,他就会独自离开后面的骑手去追更快的人,给定其他人的出发时间,让你求查理到目的地最短时间。
分析:查理要跟随别的人一起去目的地,并且每次跟随时如果有更快的人超过他,则就去追最快的人。而现在要求查理到目的地最短时间,这个时候我们就可以做一个等效,最快的那个人到目的地的时间就是查理到的最短时间,也就是让查理跟着所给数据中最快的那个人。
在查找最短时间时,可以直接使用函数min( , )进行比较,找出最小的那个,时间:路程/速度+每个人出发的时间。

Y
题目大意:一个人生产酸奶,酸奶在仓库中可无限存放,已知每份酸奶每周的存放维护费用,每份i周的生产成本,i周是交付数量,以及将要交付的周数,让你求得最小花费。
分析:根据题目我们可以看到,前面的已知条件很多很复杂,因此我们可以选择从后往前看,先看我们要求什么,求得是最小花费。我们有两种方式得到要交付的酸奶,第一种就是先生产,先交付;第二种就是,某周生产出来的酸奶一直在仓库中放着,那么我们在交付时,所花费的前就不是该周规定的成本,而是那个某周的成本加上每个周的维护费用,为了使花费最小,我们仅需要比较到底是每周规定的成本最少,还是在某周生产出来一直存着到那天取出来成本最少。在进行比较中仅需要一个min函数。

第四类:平均分配

这种题其实理解后就发现不是很难,整理的目的主要是觉得这种分配方式比较简单容易理解,以前没有遇到过。

Q
题目大意:已知几罗积木,积木的总个数和罗数是倍数关系,现在要使每一罗积木个数相同,要求得移动积木的最小次数。
分析:由于罗数和总数是倍数关系,因此很容易求得一个平均值,该平均值就是每一罗的积木数目。现在,我们要将这些积木移动成刚刚所求得的数目,那么如何使移动次数最大呢?根据贪心思想,为了更高效的移动,我们要先对原积木数和平均值的差进行一个由大到小或者由小到大的排序,并不影响结果,假如由小到大,就相当于将每一罗按照原积木数由小到大排列,从矮的开始注意移动。如果差值是一个负数,则在该罗中需要加上想应的积木数目才能使差为零(为零代表该罗移动完毕),而对应的就是后面差值大于零的元素减去相应的积木数目,因为必定是积木多的移到积木少的,因此我们可以得出,移动次数,就等于差值小于零时差的和,或者差值大于零时差的和。

第五类:性价比

性价比=性能/价格,在做F时,刚开始并未第一时间想到性价比问题,不过值得注意的是F中有一个a%,所以很想弄清楚a%是什么。知道已经有的猫粮,也知道每个房间需要的猫粮,消耗多少猫粮就可以获得多少鼠粮,鼠粮获得量最多,那肯定就要让已有猫粮都消耗掉,而且不单单要消耗,还得保证可以用消耗的猫粮换取最高价值的鼠粮,联系背包问题,将背包装满,并且还要使装的价值最大,于是想到性价比的概念,这个时候a%的作业也一目了然。

F
题目大意:老鼠有M磅猫粮,准备和看守仓库的猫交换食物,仓库有N个房间,第i个房间有J[i]磅老鼠喜欢的食物,需要F[i]磅猫粮,老鼠不需要交换仓库里所有的鼠粮,如果支付F[i]*a%磅猫粮,它可以得到J[i]*a%磅鼠粮,求老鼠能获得鼠粮的最大数量。
分析:由于猫粮有限,而我们要用有限的猫粮换取最多的鼠粮,因此引入J[i]/F[i]最大,即找最高性价比,并将性价比由高到低排序。最靠前的代表最值得交换的,在遍历元素时,比较所有猫粮是否大于等于这个房间需要的猫粮,若大于则可直接交换相应的鼠粮,若猫粮不够,则用剩下的猫粮乘以该房间的性价比最后相加即所得鼠粮。

第六:下面有两道题,虽然并没有划分出属于哪一类题型,但是觉得很有意思,想整理一下:

H
题目大意:有n堆木棍,每根的长度和重量都已经知道,现在要逐一进行加工,加工需要时间,第一根木棍需要的时间为一分钟,在加工完长度为l重量为w的木棍后,如果i<=i’,w<=w’,则机器不需要重新设置长度为l’重量为w‘的木材,否则需要一分钟进行重置,而你需要找出最小设置时间。
分析:典型的贪心问题,要找最小时间,而如果满足最小时间,也就是让重置次数减少,由题意知如果前一个木棒的长度重量都小于等于当前木材的长度重量则不需要重置,因此我们就按照长度重量进行升序排列:先按照长度升序,若长度相同就重量升序。重要的是下面要开始遍历元素所出现的情况。
在遍历时会发现,每个元素的确是按照长度由小到大,但是总会有一些元素他们的重量并非升序,而只要有一个性质不是升序,那么就必须要重置,因此我们只需找出重量性质不是升序的元素。所以定义一个bool类型的标量用来标记。首先第一个元素肯定要有一分钟的时间,加完时后将其标记,剩下的继续往后遍历,如果碰到一个元素没有被标记并且重量小于等于下一个的重量则标记,并将比较元素下移,而剩下没有标记的则就是不满足条件的,则加时。

N
题目大意:有M个人,每个人有N张牌,牌最大号是N*M,每张牌都相差一个好吗,现在要出牌,每一句牌号最大的胜出,当所有牌都出完时则比赛结束,已知自己的牌号,现在要求自己所能胜出的最少局数。
分析:已知自己的牌,已知牌的总数,又想赢,那么我们只需要每局从最大的那张开始出,判断自己的最大是否为该局的最大即可。首先将自己的牌由大到小排序,然后将全局中的牌号又大到小开始遍历,将自己的牌与全局牌号进行比较,如果自己的牌就是该局最大牌号,则胜利,若自己的牌是下局最大牌号,但是由于每次都要出自己当前所持有最大牌,所以该局无法取胜,此时全局中在该局的最大牌也已经消耗。
举个例子:
最大牌66
自己持有:
66 65 63 62 61 57 56 53 50 48
从第一个全局最大开始:我的66 一定赢,下一句我的65一定赢,第三局,最大应该是64而我是63,所以我一定不赢,为什么是一定无法赢,而不是可能无法赢?因为我们要求最少可赢局数,如果这一局它不出64那我们就赢了,而再下一句你会发现,它没有比62更大的牌,那我们就相当于赢了两局,而明明前一局是可以不赢的,为了保证赢得局数最小,我们要把前面的64消耗掉,也就是说,所有的牌都按照由大到小出,不可跳牌,这样就可以求得最优解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值