2.1-2.2完成贪心专题
题目链接:
下面是题解。
A
使用贪心算法,先将木棍排序(两个关键字依次升序),用数组p存储木棍是否已经被处理(未被处理为0),然后从头遍历,碰到第一个根p!=0的木棍,存储其长和重,记为curl和curw,继续往后遍历,对每根p!=0的木棍,若其l>=curl&&w>=curw为真,则处理这根木棍,并更新curl和curw;反复循环直至所有木棍被处理。
B
要求至少能赢的局数,共N*M张卡片,先降序排序,然后分析:
1.手上最大的k张卡片,每一张都能赢一局;
2.从N*M-k开始往下遍历每一张不是自己的卡会输一局,每张自己的卡会赢一局,记录最大的可能获胜局数x;
则至少能赢k+x局。
C
本题关键在于弄清贪心的方法。根据题意,所有作业完成时间都为1天,并且超过截止时间之后扣分不会变化,即如果作业超过截止时间,就不需要再考虑其完成时间。
用数组day来标记第i天完成了第j份作业,数组day全部初始化为-1,表示该天还没有安排作业。将作业按分数降序排序。每一份作业需要尽量排在其截止日期或之前,且尽量靠后的位置,这样总扣分最少。
证明:
依次考虑每份作业。
假设该份作业的截止日期为t,那么,他只需要在前t天中的任意一天做完就能不扣分,否则扣分。根据贪心规则,后面的作业分数都小于等于当前作业,那么如果因为完成该份作业导致另外一份作业无法完成,总扣分不会更多。这样,在相同的作业完成数量下,完成的作业的分数一定是尽可能大的。
在这个前提下,我们希望完成尽可能多的作业。假设下一份作业的截止时间为s,
若s>=t,那么可供下一份作业选择的完成时间不变;
若s<t,那么若果该份作业被安排在前s天,可供选择的完成时间会少1。
因此,作业的完成时间应尽量推迟,并且先安排分数多的作业,就可以使扣分最少。
D
典型区间不想交问题,将各区间的左右端点记为ai和bi,按bi升序,ai降序排列,用cur标记当前区间的最右端,从前往后遍历,如果ai<=cur,那么可以选择,更新cur并计数。
E
各个仓库按照性价比(java豆/猫粮)降序排序,按顺序拿,若猫粮不够,则按比例拿走部分,全部相加即可。
F
其实看明白问题的话非常轻松,只需要计算每个走廊对应的最多占用次数即可,记得将房间号加1再除2,得到对应的走廊号,并注意每次搬运的前后节点也看作占用。
G
优先安排大包裹。其中5*5的安排完只能安排1*1;4*4和3*3的安排完,剩余空间优先安排2*2,再安排1*1.若2*2和1*1的包裹还有剩余,则令取包裹安排即可。
H
对于每两头牛之间的长度l,假设左边i头牛,右边n-i头,那么区间内有i*(n-1)对牛的声音,总声音i*(n-i)*l,各段依次相加,最后乘2即可。
I
策略同C题,我代码都没怎么变。
J
对于每一个岛屿,要能接受到信号,雷达的安装都有一个范围,记为[ai,bi]。那么一个雷达的最贪安装位置为ai或者bi处,这里我选择bi。将所有雷达按照bi升序排序,遍历,第k个雷达安装的位置为xk,若ai<=xk<=bi,那么不需要额外的雷达,否则,雷达应该安装在bi处。计数输出即可。
K
所有泥潭升序排序,用一个变量cur标记当前铺了木板的最右端。
对第i个泥潭,其边界为ai和bi,分三种情况:
1.bi<=cur,不需要另外铺木板;
2.ai<cur,应当从cur开始铺木板;
3.cur<=ai,应当从ai开始铺木板;
铺完木板,计数,更新cur并继续循环即可。
L
该题要素较多,比较繁琐。
(但是只要够贪,,,仍然很麻烦)
对于n口池塘,如果需要到第k口池塘钓鱼,那么路过的1-k-1口池塘里面的鱼都能随意的钓并且不花费额外的走路时间(可以先算好在哪一口池塘钓几分钟)。
那么考虑k从1遍历到n,选择期望钓鱼sum最多的结果。
对于每一个k,剩余时间为总时间减去走路的时间,对池塘采用优先队列,排序方式为:将前k口池塘按照现有鱼的数量降序,再按照池塘编号升序的方式排序。每一次取出队首元素,钓鱼,再入队(鱼的数量可能减少了)。
这样遍历,最后按要求输出即可。
p.s.
需要注意每一次减少鱼的数量时不能少于0,不然最终时间过剩时可能不会优先选择1号池塘;
当还没钓鱼,剩余时间就<=0的时候,可以直接跳出循环,因为后面的池塘的走路时间肯定比现在长;
仅样例之间有换行,且每个样例第一行的','后面有一个空格(被坑的有点惨);
M
(自己的思路错了,看的题解的)
题解连接:
一棵树,结点树为n ,根结点为r 。 每个结点都有一个权值ci ,开始时间为0 ,每染色一个结点需要耗时1 ,每个结点的染色代价为ci*ti ( ti为当前的时间),每个结点只有在父结点已经被染色的条件下才能被染色。 求染完整棵树需要花费的最小代价。
题解:
结论证明来源: hi.baidu.com/cheezer94/i…
结论1 :对于一个非根结点,它具有非根结点的最大权值,那么访问完它的父亲后就要立即访问它才能使得代价最小。
处理过程:
1 )建立结构体node ,结构体数组 node[i] 表示i结点的状态, node[i].c=ci 为总权值, node[i].w=ci 为当前权值, node[i].t=1 为经过这个结点需要的耗时(也可以理解为这个结点包含几个合并的结点), node[i].pre 为父结点
2 )找到一个最大权值非根结点,将其m与其父亲p合并形成一个新的结点,新结点还是原来p的位置,这个新结点的子结点为m和p的子结点;答案ans+= node[m].c*node[p].t ,表示经过父节点p后,需要经历 node[p].t 时间才到达m ,所以讲m同p合并后,总代价要加上这段路径的代价;新结点的情况 node[p].c+=node[m].c , node[p].t+=node[m].t , node[p].w=1.0*node[p].c/node[p].t (新结点权值变成算术平均值,因为到这个结点的代价被平分分给t个结点)。
3 )重复2 )直到结点只有一个为止。
4 ) ans+=∑ci ,因为本身染色需要耗时1 ,也就要支付代价ci*1.