noip提高组写题心得——贪心4例

来源:互联网 发布:新媒体与网络传播 编辑:程序博客网 时间:2024/06/06 04:38

例1:火柴排队

这道题的话关系到一个叫排序不等式的东东,额这个东西的话其实我并没有学过,但是上网查一查,贴个证明下来:

②设有两个有序数组:  及

求证: (顺序和≥乱序和≥逆序和)

其中 是自然数的任何一个排列

证明:令

由题设易知 

因为 故

所以 

即左端不等式,类似可证明右端不等式

然后捏,这个求∑(ai-bi)^2其实就是求∑ai^2+bi^2-∑aibi那么就是求∑aibi最小值,用排序不等式证明。就是要使得这两个数列大对大,小对小。那么这样纸的话,只要用贪心吧其中两个数列排序。编号对应之后存到一个数组里,然后就是求逆序对咯(因为每当有一个逆序对,就要换一次)然后自然树状数组敲出来搞定!

例2:国王的游戏

其实和上一题一样,两道题玩的都是数学。这题的话数学的证明比上一题更难一些。嗯,首先来考虑。明显大臣们排列的方式一定是有规律的。我们可以猜测是与他们手上的数有关的某种大小关系。那么,涉及到排序,我们就要涉及到交换的条件(冒泡的思想),那么我们就试试看如果两个大臣要交换,那么他们必须满足什么条件,从结论往回推导。(当然这两个大臣是相邻的)

设大臣左手上的数是Ai,右手上的是Bi,之前所有人左手的乘积是S,如果把这两个人交换了,对于其他人是没有影响的。我就可以放心地在这里推导了

交换前:ans1=max(S*a[i]/b[i+1],S/b[i]);

交换后:ans2=max(S*a[i+1]/b[i],S/b[i+1])

我们目的是:如果ans2<=ans1那么ai,bi,ai+1,bi+1满足什么条件

四种情况自己都考虑一下,最后得出的结论是必须满足a[i]*b[i]<=a[i+1]*b[i+1]

所以按照这个顺序排序,然后高精乘法选出最大的,Ok啦

例3:观光公交

比较难下手的一道题,一样地,我们来看题目分析:

题目条件比较多,再此一一列举:

1.      相邻景区有一条带权路。

2.      乘客在固定时刻到达一个景区,从一个景区做观光车到另一个景区

3.      观光车以固定速度,固定向前行驶每一条路径,要载上每一位乘客

4.      有k个加速器可以是任意一条路径的权减一

5.      求最小的乘客旅行时间(下车时间-到站时间)

我们一条一条定点分析。

第1条是题目环境,忽略。第2,3条值得推敲。观光车每次都要等所有乘客上车以后载人,意味着对于每一个站点,都有一个最早发车时刻等于最晚到车站的那个乘客的时刻。我们设这个数组为bt[i]这样子的话,就比较容易出现断层,分类的情况。动态规划可能比较难进行操作。所以不太可能使用动态规划。

对于4,发现比较难下手。题目的关键在于此。但是比较不好破解,先跳过。

对于5,是要求的东西。我们发现,每个乘客的到站时间,是固定的,题目已知的。而下车时间,是未知的,下车的站点,是已知的。那么对于每一个站点来考虑。如果这个站点的到站时间最早,那么对于这个子问题肯定是最优的,从而可以达到整体的最优。所以这里采用贪心的办法。

确定贪心之后,再来看4。这个加速器的使用,如果以动归的角度来考虑,并不是不行。但是我考虑之后,发现数组根本开不了。因为1:不知道要用时刻还是站点来操作。2:时刻与站点有很大的联系。一个时刻的改变会牵扯到之后状态的改变。所以否定了。那么,如果用贪心的角度的话,那么对于每一个加速器,其最优的办法就是能够影响到最多的旅客的旅行时间。如何理解一个加速器对于旅客的影响呢?首先我们上面分析过,影响一个旅客的旅行时间的因素是到站的时间。意味着我们一定有一个f[i]储存到第i个站点的最优到站时间。同时还有一个sum[i]表示再i站下车的旅客数量。如果一个加速器在i~i+1路段使用,那么一定会影响到i+1站下车的旅客。而对于i+2个车站。如果说第i+1个车站使用加速器的到站时间小于bt[i]那么也就是说,不管有没有用加速器,在这个景点我要等到的时间是确定的,也就无所谓使用不使用了,所以对于之后的车站都没有影响。而如果反之,则仍然有影响。而继续考虑下去,条件仍然相同。所以我们就可以使用递推的方式来地推出在第i~i+1路段能影响到第几个景点。然后求出这个加速器可以影响几个乘客。然后每一次求出影响力最大的加速器,使用它,然后重新维护f数组。然后再一次循环,直到求出正解。这个贪心就是正确的了。

例4:疫情控制

这道题是目前为止我做过最难的一道贪心题,要进行好多优化,否则会很容易错误。首先看看总体的思路分析:

这道题又是一道最小最优解类型的题目。但是这个最小里面其实隐含着的是一个最小最大问题。为何?因为控制疫情的时间是按照移动时间最大的那个军队来算的。搞清楚这一点,我们就可直接确定,这题肯定是二分答案题了。

然而二分答案是挺简单的,主要是怎么进行验证?

首先,我们搞清楚一点:对于那些在规定时间之内无法到达首都的军队,或者刚刚好到达首都的军队,很明显,往父亲结点走是最优的选择,所以对于这些点,可以进行贪心。

所以由于这些点,我们可以先一步进行一次贪心,贪心过后,从每个叶子节点往上搜,一直搜索到这棵树的第2层,如果到这里还没有可以控制城市疫情的,那么这个节点,就需要哪些可以走到首都的人来进行调配了。

最难的一点(当时就卡在这里):对于可以走到首都的军队,如果我令他每个人都走到首都,然后按照需要到达的结点路径大小和这些人的时间分别进行排序,令每一个人都是最优的,是可以得到部分解的。但是,注意,对于那些军队,他走到首都之前,本身就会经过一个第二层的结点,那么就不符合贪心无后效性的特点了。

对于这个,我上网搜了题解,其办法就是:从剩余时间最少的那个军队开始。如果说他经过的那个结点是需要封锁的,那么让他来封锁一定是最优的。为何?因为他是剩余时间最少的,同样地封锁一个结点,让他封锁一定比让别人封锁更优。然后我们就从小到大排序一下,然后看看可不可以封锁,不可以则对于另外的结点可不可以走过去封锁,然后不行就是废掉的,看看能不能封下所有的结点咯。

额。。这题其实还有一个非常非常坑的地方,就是这题的输入居然没告诉你那个是父亲那个是儿子,啊,,处理输入数据块烦死掉。。。

贪心的总结:

1.      首先,贪心的特征是:把一个大问题分解成为几个子问题,然后对于每个子问题,仅仅考虑其最优解,而不考虑整体的最优解,从而得出一个解,这就是贪心。

2.      使用贪心的时候,一定要注意证明是否可以从这个局部的最优解推出整体的最优解。若不行的话,很有可能只得到部分分数,得不到全部分数。

0 0
原创粉丝点击