【概述】
贪心算法是从问题的初始状态出发,通过若干次的贪心选择而得到的最优值的一种求解策略,即贪心策略。
简单来说,贪心策略是一种在每次决策时采取当前意义下最优策略的算法,做出的选择至少在某种约束条件下的局部最优解或较优解,并不一定是全局的最优解或较优解,但在某些特定的情况下,可以利用贪心算法来求得其最优解或较优解。
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即:某个状态以前的过程不会影响以后的状态,只与当前状态有关。
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质,问题的最优子结构性质是该问题可以用动态规划或者贪心算法求解的关键特征。
【一般步骤】
- 建立数学模型来描述问题;
- 把求解的问题分成若干个子问题;
- 对每一子问题求解,得到子问题的局部最优解;
- 把子问题的局部最优解合成原来问题的一个解。
简单来说,就是根据要求,不断选择最大/最小的,直到满足/不满足条件为止
/*
候选集合A:问题的最终解均取自于候选集合A。
解集合S:解集合S不断扩展,直到构成满足问题的完整解。
解决函数solution:检查解集合S是否构成问题的完整解。
选择函数select:贪心策略,这是贪心算法的关键。
可行函数feasible:解集合扩展后是否满足约束条件。
*/
Greedy(A)
{
S={ };//初始解集合为空集
while (not solution(S))//集合S没有构成问题的一个解
{
x=select(A);//在候选集合A中做贪心选择
if feasible(S, x)//判断集合S中加入x后的解是否可行
S = S+{x};
A = A-{x};
}
return S;
}
【例题】
1.最优选择问题
问题:给出 n 个物品,第 i 个物品重量为 wi,选择尽量多的物品,使得总重量不超过 C
贪心策略:由于只关心物品重量,因此将所有物品按重量从小到大排序,依次选择每个物品,直到装不下为止
- 纪念品分组(洛谷-P1094):点击这里
- 合并果子(洛谷-P1090):点击这里
- 拦截导弹问题(信息学奥赛一本通-T1322):点击这里
- 书架(信息学奥赛一本通-T1228):点击这里
- 接水问题(信息学奥赛一本通-T1233):点击这里
- 统计数字(信息学奥赛一本通-T1239):点击这里
- 整数区间(信息学奥赛一本通-T1324):点击这里
- An Easy Problem(信息学奥赛一本通-T1223):点击这里
- Turn the Rectangles(CF-1008B):点击这里
- 数列分段Section I(洛谷-P1181):点击这里
同题:数列分段(信息学奥赛一本通-T1428):点击这里
- 排队接水(洛谷-P1223):点击这里
同题:排队接水(信息学奥赛一本通-T1319):点击这里
- 电池的寿命(信息学奥赛一本通-T1229):点击这里
- 删数问题(信息学奥赛一本通-T1321):点击这里
- 装箱问题(信息学奥赛一本通-T1226):点击这里
- 最小新整数(信息学奥赛一本通-T1231):点击这里
- 数列极差(信息学奥赛一本通-T1427):点击这里
- 钓鱼(信息学奥赛一本通-T1431):点击这里
- 处女座的期末复习(2019牛客寒假算法基础集训营 Day2-J):点击这里
- 项链(2019牛客寒假算法基础集训营 Day6-C):点击这里
- Polycarp's Practice(CF-1006B):点击这里
- Songs Compression(CF-1015C):点击这里
- 超级赛亚ACMer(HDU-5246):点击这里
- Sequence(BZOJ-1345):点击这里
- Boxes and Candies(AtCoder-2152):点击这里
- Roundgod and Milk Tea(HDU-6667):点击这里
- New Year Snowmen(CF-140C)(map+优先队列):点击这里
- Polycarp and Div3(CF-1005D)(前缀和):点击这里
2.部分背包问题
问题:n 个物品,第 i 个物品重量为 wi,价值为 vi,在总重量不超过 C 的情况下让总价值尽量高,每一个物品可以取走一部分,价值与重量按比例计算
贪心策略:本质上在最优选择问题的基础上加了价值项,不能仅考虑重量因素或价值因素,应该综合考虑两个因素,即优先选择价值和重量比值最大的,直到重量和为 C,需要注意的是,由于每个物品只能选择一部分,因此一定可以让总重量恰好为 C,而且除了最后一个物品以外,其他物品要么不选要么全选
- Yogurt factory(POJ-2393):点击这里
- 混合牛奶(洛谷-P1208):点击这里
- 金银岛(信息学奥赛一本通-T1225):点击这里
- Protecting the Flowers(POJ-3262):点击这里
- Ride to Office(信息学奥赛一本通-T1227):点击这里
- 处女座的训练(2019牛客寒假算法基础集训营 Day3-D):点击这里
- Cow Acrobats(POJ-3045):点击这里
- Annoying Present(CF-1009C):点击这里
- Allowance(POJ-3040)(小数背包):点击这里
- Minimum Value Rectangle(CF-1027C)(数学推导):点击这里
3.乘船问题
问题:n 个人,第 i 个人重量为 wi,每艘船载重为 C,最多可乘 2 个人,现在想用最少的船将所有人运走,问船的数量
贪心策略:将所有人按重量从小到大排序,依次考虑最轻的人 i,如果每个人都不能与他一起乘船,那么就只能每个人都乘一条船,否则,其能选择能与他一起乘的人中重量最终的一个 j,这样使得眼前的浪费最少
- 独木舟(51Nod-1432):点击这里
- Balloons(CF-998A):点击这里
4.选择不相交区间问题
问题:给定 n 个开区间 (a,b),选择尽量多个区间,使得这些区间两两没有公共点。
贪心策略:将每个区间按结束时间从小到大排序,即按:b[1]<=b[2]<=...<=b[n] 的顺序排序,最初选择结束时间最早的活动 temp=b[1],然后每次考虑最早的开始时间 a[i],如果比当前选择的区间的结束时间要晚 a[i]>temp,那么就选择这个区间,即有:temp=b[i],res++
- 线段(信息学奥赛一本通-T1429):点击这里
- 活动选择(信息学奥赛一本通-T1323):点击这里
- 活动安排(信息学奥赛一本通-T1422):点击这里
- 不重叠的线段(51Nod-1133):点击这里
- 凌乱的yyy(洛谷-P1803):点击这里
- Muddy roads(POJ-2437):点击这里
5.区间选点问题
问题:给定 n 个闭区间 [a,b],在数轴上选尽量少的点,使得每个区间内都至少有一个点
贪心策略:首先按照区间右端点从小到大排序,然后从区间 1 到区间 n 进行选择,对于当前区间,若集合中的数不能覆盖他,则将集合末尾的数加入集合
- 种树(信息学奥赛一本通-T1423):点击这里
- Sunscreen(POJ-3416):点击这里
- 美食(2019牛客寒假算法基础集训营 Day6-D):点击这里
- X: Yet Another Die Game(AtCoder-2298):点击这里
- Cutting(CF-998B):点击这里
6.区间覆盖问题
问题:给 n 个闭区间 [a,b],选择尽量少的区间覆盖一条指定的线段区间 [s,t]
贪心策略:将所有的区间按左端点从小到大排序,依次处理每个区间,每次选择覆盖点 s 的区间中右端点坐标最大的一个,并将 s 更新为该区间的右端点坐标,直到选择的区间包含 t 为止
- 喷水装置(信息学奥赛一本通-T1424):点击这里
- Expedition(POJ-2431):点击这里
- Sonya and Hotels(CF-1004A):点击这里
- 寻找平面上的极大点(信息学奥赛一本通-T1230):点击这里
- Convert to Ones(CF-998C):点击这里
7.带限期与罚款的单位时间任务调度
问题:n 个任务,每个任务需要一个单位时间执行,任务 i 的截止时间 di表示任务 i 在时间 di 前必须完成,误时罚款 wi 表示任务 i 若未在 di 前完成,导致 wi 的罚款,确定所有任务的执行顺序使得罚款最少
贪心策略:要使罚款最少,就尽量完成 w[i] 值较大的任务,此时将任务按 w[i] 从大到小排序,按排好的顺序对任务进行安排:使得处理任务 i 的时间在 d[i] 之内又尽量靠后,如果 d[i] 时间之内的时间都已排满,就放弃处理该任务
- 智力大冲浪(信息学奥赛一本通-T1426):点击这里
- 家庭作业(信息学奥赛一本通-T1430):点击这里
8.其他
- 小a与"204"(2019牛客寒假算法基础集训营 Day1-B)(贪心+构造):点击这里
- Walk and Teleport(AtCoder-2287)(贪心+线性DP):点击这里
- 均分纸牌(洛谷-P1031):点击这里
同题:均分纸牌(信息学奥赛一本通-T1320):点击这里
- 糖果传递(信息学奥赛一本通-T1432)(环形均分纸牌):点击这里
- Merging Two Decks(CF-234H)(贪心+vector):点击这里
- Game(HDU-6669)(贪心+区间交集):点击这里
- Summarize to the Power of Two(CF-1005C)(map+贪心):点击这里
- Stay Real(HDU-6645)(小根堆性质):点击这里