3.13-3.20学习总结

贪心算法小结(1)

定义:1.贪心算法是按照某种最优策略将复杂问题分解成子问题,从而能够解出整个问题的最优解
2.可以看出,贪心算法最鲜明的特征是先从局部考虑,进而找到整个问题的最优解
3.贪心算法优先级高,因为时间复杂度比其它算法都要低,因此若此问题能够用贪心算法解决的话,一般是最优解
判定是否是贪心方法:先对问题进行模拟,找到最一般的问题的解决方案,同时在这个过程中对解决方法进行优化,选择更简洁的方式来处理子问题,进而处理全部问题,而这个最简洁的方式就是贪心算法

类型题:

1.单指针问题
代表题目:最优装载问题(入门题)
题目介绍:某艘船的载重量为C,每件物品的重量为wi,要将尽量多的物品装入到船上
思路:将重量进行由小到大排序,逐个放置于船上,最终判定是否超过船的载重
核心方法:单指针,对每件排好序的货物进行数组指针处理,逐个判定
也就是说仅有一个量需要判定
2.比例问题
代表题目:背包问题(入门题)
题目介绍:有N件物品和一个容量为V的背包。第i件物品的费用,是w[i],价值是val[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
思路:将价值与重量进行除法处理(也就是性价比),进行排序,选择性价比最大的,转化为单指针问题
核心方法:当两个依据量都不可以处理问题时,考虑其比值是否可以处理问题,从而解决题目
3.区间调度问题
注:1.结束时间越早之后可选的工作也就越多。这是该算法能够正确处理问题的一个直观解释
2.区间调度题目出现次数较多,一般有以下类型
代表题目1:选择工作问题
有n项工作,每项工作分别在si时间开始,在ti时间结束
你的目标是参与尽可能多的工作,那么最多能参与多少项工作呢?
思路:选择结束时间作为排序标准,从结束时间早的开始选择,并进行代码书写
核心方法:结束时间越早之后可选的工作也就越多。这是该算法能够正确处理问题的一个直观解释
代表题目2:最小个数问题
读取闭区间的个数及它们的描述,找到一个含元素个数最少的集合,使得对于每一个区间,都至少有一个整数属于该集合,输出该集合的元素个数。
思路:仍然选择结束位置为排序标准,注意最少包含,选择最后一个能够使元素尽可能的包含进去
小结:也就是说每次都是以结束时间为判定标准,这是这种题目的常规思路,拓展则是在此加上一系列的限定条件,难度也是比较低
代表题目3:选课问题
一共有N门课可以选,但选课时每次必须间隔5分钟。例如你在5分07秒选了一门课,那必须在10分07秒选下一门课.。每一门课的的选课是有时间限制的,你只能在Ai到Bi之间选中第i门课。求你能选择的课最多多少门
思路:首先要按照区间调度进行结束时间排序,这是这种题目的第一步
第二步是根据题意进行选课,已经知道只能每隔5分钟选一次课程,则从1到5逐个时间点进行选课,看哪一个时间能够选得最多的课程
第三步是当到相应时间时,选择最早结束的课程(这是这种方法最明显的体现)
z
代码中也有要注意的问题(实现代码部分书写)

for(int start=0;start<5;start++){
//枚举5个选课时刻,这也是这一个for循环的意义所在
            for(int i=0;i<N;i++)vis[i]=false;
            //设标记意义:已经选过的课程不能够再选
            //这一点也是区间调度问题内需要注意的内容:看是否允许重复调用
             int ans=0;
            for(int i=start;i<1001;i+=5){枚举所有选课时刻
                for(int j=0;j<N;j++){
                //循环这么书写的话要考虑到重复选择
                    if(i>=node[j].l&i<node[j].r){
                        vis[j]=true;
                        //选择之后要标记上,防止重复选择
                        //因为也有些课程满足时间但已经选过一次了
                        ans++;
                        break;
                        //选择之后这一时刻已经确定,直接跳出
                    }
                }
            }

4.双指针 问题
核心:(1)双指针的初始位置;(2)双指针的移动方式(什么时候移动,移动方向,移动之前需要判断是否会越界);(3)遍历的结束条件。基本上解题套模板时也是这三点明确了就很好写
代表题目1:字典序问题(入门级)
给定长度为N的字符串S,要构造一个长度为N字符串T。T是一个空串,反复执行下列任意操作:
从S的头部删除一个字符,加到T的尾部;
从S的尾部删除一个字符,加到T的尾部;
目标是要构造字典序尽可能小的字符串T。
思路:这个题可以再构造反字符串,同时构造两个数组,一个指向第一个,一个指向第二个,逐个比较输出较小的内容
注:在这个题目中,双指针的初始位置,双指针的移动方式,以及遍历的条件均很明显
代表题目2:分发饼干
每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。目标是尽可能满足越多数量的孩子
思路:双指针排序,均按照从大到小排序,将胃口、尺寸进行排序,也就是双指向,将尺寸逐个与胃口比较,按照大满足大的原则(这个原则的优势很明显,同时也能够确保不会出现例外情况)
5.其他贪心类题目(思想)
代表题目1.相撞求最小质量
给出n 个物体,分别给出每个的质量,并且两个物体(假设质量分别为m1,m2)相撞的时候变成一个物体,质量为2sqrt(m1m2),并且只会出现两个两个物品碰撞的情况,问最终能得到的物体的最小质量是多少。
思想:模拟思想
对于任何一道acm题来讲,都极难读完题目就有思路,需要先模拟这个题的过程,并对自己的演化过程进行优化,最终选择最优解决方案
对于这个题模拟:a>b>c(质量)两种情况
Ans = sqrt(sqrt(2 * a * b) * c * 2)
Ans = sqrt(2 * a * sqrt(2 * b * c))
能够看出尽可能让大数开最多次根号,所以先排序,让大数逐步开根号,进而求得最小值
代表题目2:摸牌问题
有m个人,每人得到n张牌,牌的号码是1到n*m之间的任意n个数,每张牌都只有一张,问我至少能赢多少局
思想:正难则反
正着思考不容易思考,则可以反向考虑,问自己至多输多少局,也就是将对方的牌从小到大逐步和自己的牌比较,如果自己的牌有比对方最小牌小的,则自己就会输一次,逐步累加,最后用总轮数减去自己输的次数即可解决题目

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值