贪心算法

贪心算法

总结

往往伴随着排序

贪心选择 + 最优子结构(关键)

贪心选择:对子问题进行一系列的局部最优选择。
最优子结构:问题的最终解可以转化为子问题的解。

作当前来看最好的选择,不从整体最优考虑

因此,当尝试使用贪心算法时,无需从全局的角度进行考虑,短视/简单地来看待问题,无需将问题复杂化!

局部最优

DP和贪心

相同点:都要求问题具有最优子结构
不同点:贪心使用自顶向下的方式,通过某种策略选择某一个子问题后,没被选择的子问题直接抛弃,只在上一步选择的基础上继续选择,当前最优 -> 下一阶段的当前最优······(局部最优)显然最终结果不一定是全局最优;而DP从边界开始,考虑了所有的子问题,继承得到最优结果的解,由于重复子问题,后期可能还会继承

经典问题

区间覆盖问题

区间完全覆盖问题
  1. 问题描述:给定一个长度为m的区间,再给出n条线段的起点和终点(闭区间),求最少使用多少条线段可以将整个区间完全覆盖。

  2. 贪心策略:将问题看成长度为m-1的子区间拓展到长度为m的完整区间,为使用最少的线段,选取满足条件(即左端点<=子区间右端点)的区间中右端点最大的线段(局部最优)。

  3. 伪代码

    curSection.l = 1;
    curSection.r = 1;
    sort(sections);  // 对区间的左端点进行排序
    while(curSection.r <= maxL):
        for i : 1 to N:
            if(seciton[i].l <= curSection.r):
                maxR = i;
        choose(maxR);
        curSection.r = maxR + 1;
    

种树

  1. 问题描述:一条街的一边有几座房子。因为环保原因居民想要在路边种些树,路边的地区被分割成块,并被编号成1…N;每个部分为一个单位尺寸大小并最多可种一棵树,每个居民想在门前种些树并指定了三个号码B,E,T,这三个数表示该居民想在B和E之间最少种T棵树。当然,B≤E,居民必须记住在指定区不能种多于区域地块数的树,所以T≤E-B+l。居民们想种树的各自区域可以交叉。你的任务是求出能满足所有要求的最少的树的数量。

  2. 贪心策略:对于h个区域,若其不交叉,此时总数即为各区域的最低数目;若有交叉,则需要尽可能将树种在交叉区域,则目标可转换为求min{各区域数量和-交叉数},将h分为h-1和1考虑,要使h-1区域与最后一个区域交叉最多,显然是h-1区域将树种在末尾的交叉数量更多。(通过数轴更好理解)

  3. 其他解法:差分约束系统??

智力大冲浪

  1. 问题描述:首先,比赛时间分为n个时段(n≤500),它又给出了很多小游戏,每个小游戏都必须在规定期限ti前完成(1≤ti≤n)。如果一个游戏没能在规定期限前完成,则要从奖励费m元中扣去一部分钱wi,wi为自然数,不同的游戏扣去的钱是不一样的。当然,每个游戏本身都很简单,保证每个参赛者都能在一个时段内完成,而且都必须从整时段开始。

  2. 贪心策略:尽可能选择奖励最多(扣钱最多)的游戏完成,而要使完成的游戏数量最大,将游戏的开始时间尽可能靠近最晚开始时间(这里就是结束时间),从而达到局部最优解。

  3. 解决步骤:

    • 先对游戏按奖励金额大小降序排序
    • 顺序遍历游戏,找到最靠近最晚开始时间(结束时间)的时间点,将其安排在该点,获得游戏的奖励金额,并对该点作已按安排处理

github地址:https://github.com/jyccccc/PATPATPAT

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值