贪心
引用《算法笔记》内容
简单贪心
贪心是求解一类最优化问题的方法,它总是考虑在当前状态下局部最优(或较优) 的策略,来使全局的结果达到最优(或较优)。显然,如果采取较优而非最优的策略(最优策略可能不存在或是不易想到),得到的全局结果也无法使用最优的。而要获得最优结果,则要求中间的每步策略都是最优的,因此严谨使用贪心法来求解最优化问题需要对采取的策略进行证明,证明的一般思路是使用反证法及数学归纳法,即假设策略不能导致最优解,然后通过系列推导来得到矛盾,以此证明策略是最优的,最后用数学归纳法保证是全局最优。不过平常使用无须严格证明。因此,如果在想到某个似乎可行的策略,并且自己无法举出反例,那就勇敢的实现它。
举例: 现有月饼需求量为D,已知n种月饼各自的库存量和总售价,问如何销售这些月饼,使得可以获得的收益最大。求最大收益。
思路:
步骤1:这里采用“总是选择单价最高的月饼出售,可以获得最大的利润”的策略。
因此对于每种月饼,都根据其库存量和总售价来计算出该种月饼的单价。
之后,将所有月饼按单价从高到低进行排序。
步骤2:从单价高的月饼开始枚举。
① 如果该种月饼的库存量不足以填补所有需求量,则将该种月饼全部卖出,此时需求量减少该种月饼的库存量大小,收益增加该种月饼的总售价大小。
② 如果该种月饼的库存量足够供应需求量,则只提供需求量大小的月饼,此时收益增加当前需求量×该种月饼的单价,而需求量减为0 。
这样,最后得到的收益即为所求的最大收益值。
区间贪心
稍微复杂一点的问题,即区间不相交问题:给出N个开区间(x,y),从中选择尽可能多的开区间,使得这些开区间两两没有交集。
首先考虑最简单的情况,如果开区间I1 被开区间I2 包含,如图(a)那么显然选择I1 是最好的选择,就有更大的空间去容纳其他开区间。
接下来就把所有开区间按左端点x从大到小排序,如果去除掉区间包含的情况,那么一定有y1 > y2 > ……> yn 成立,如图(b),现在考虑应当如何选取区间。发现I1的右边有一段是一定不会和其他区间重叠的,如果把它去掉,那么I1的左边剩下的部分就会被I2包含,如图,应当选择I1 。因此对于这种情况,总是先选择左端点最大的区间。(或总是先选择右端点最小的区间)
总是先选择左端点最大的区间,然后由大到小进行:
#include<bits/stdc++.h> //万能头文件
using namespace std;