贪心算法(活动选择、分数背包问题)

2024-05-05 16:44

本文主要是介绍贪心算法(活动选择、分数背包问题),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、贪心算法

        贪心算法是指:在对问题求解时,总是做出在当前看来是最好的选择,而不从整体最优考虑,做出的仅是在某种意义上的局部最优解。                                                                                            贪心算法不是对所有问题都能得到整体最优解,但能产生整体最优解或者其近似解

        基本思路:

        通过一种贪心的想法,使得得到当前的局部最优解,从而拓展至整体最优解(不一定)。所求问题的整体最优解可以通过一系列局部最优的选择,换句话说,当考虑做何种选择的时候,我们只考虑对当前问题最佳的选择而不考虑子问题的结果。这是贪心算法可行的第一个基本要素。贪心算法以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。

        贪心算法的弊端: 

              1.不能保证得到的最后解一定是最佳的,可能存在近似解(不保证一定的正确)。

              2.不能用来求最大或最小解问题。

              3.只能求满足某些约束条件的可行解的范围。

二、活动选择问题

        1.题目描述:

    假定有一个n个活动(activity)的集合S={a1, a2, ..., an},这些活动使用同一个资源(例如一个阶梯教室),而这个资源在某个时刻只能供一个活动使用。 每个活动ai都有一个开始时间si和一个结束时间fi。 如果两个活动[si, fi)和[sj, fj)不重叠,则称它们是兼容的

        目标: 找到互相兼容的最大活动子集

        互相兼容的最大活动子集样例:

   

            2.贪心思想的策略

                针对每个新活动,计算其与已经举办过的活动之间的兼容性。

                ①最早启动优先:对于所有活动,以 si 升序排列

                ②最短时长优先:以 fi - si 升序排列

                ③最少冲突优先:对于每个 i,统计与其冲突的活动数量 ci ,以 ci  升序排列

                ④最早结束优先:以 fi 升序排列

        贪心算法不保证正确性,以上四种想法,对于 ① ② ③ 均存在反例验证出其错误。

        3.贪心思想的正确性验证(最早结束优先): 

        设E={a1,a2,.....,an}为活动集合,且E中的活动是按照活动结束时间升序排列的,显然a1为最早结束。设A是问题的一个最优解,明显A是E的一个子集,设A的第一个活动为k

        ① 若 k = a1,则A的第一个活动就是最早结束的,故A是以贪心选择开始的最优解

        ② 若 k ≠ a1,设集合B=(A-{k})∪a1 ,即用活动a1可替换掉活动k

        因为a_{1}的结束时间小于k,故a_{1}k提前结束。另外由于A中的活动是相容的,故B中的活动也相容。      又因为A中的活动个数和B中的活动个数相同,故B也是最优解(需要注意的是最优解一般不唯一)。所以 B 是一个以贪心选择活动 a1 为开始后的最优解。

        或者另一种想法:

        对于最早结束的第一个活动 a1, 局部最优解考虑a1,再考虑 a2 :

         若 s2>f1 a1,a2 兼容,则问题只需要考虑 a2 ~ an,问题变成了子问题 a2 ~ an 。

         若 s2<f1  a1,a2 冲突,不考虑 a1, 令 a2 为最优解的第一个活动,则此时在 a3~an 的最优解中,加上 a1 或者 a2 的活动(不冲突时),才成为整体的最优解。此时考虑 a1 或者 a2 都是最优解,活动兼容的个数都相同,所以此贪心思想是正确的。

        4. 此外该问题还存在另一种贪心思想:

        选择最晚开始的活动依次排序考虑,其他与上述思想一致。

三、拓展问题:最少资源投入

        1.问题描述

        假定有一个n个活动的集合S={a1, a2, ..., an},这些活动可以同时使用多个资源(例如一个阶梯教室),但一个资源在某个时刻只能供一个活动使用。 每个活动 ai 都有一个开始时间 si 和一个结束时间 fi 。 如果两个活动 [ si ,  fi ) 和 [ sj , fj ) 不重叠,则称它们是兼容的

        目标: 找到最少资源数量,使得所有活动能够正常举行.

         2.贪心思想:

        ①首先将所有课程按照开始时间升序排列,并且将每门课程赋予任何可兼容的教室。

        ②通过维护一个优先队列,按照结束时间升序排列(队列首端的结束时间最早),队列中的每个元素对应着各教室的结束时间。

        ③这样当新的一个活动加入时,只需要与队首元素对应的结束时间比较,若大于结束时间则直接替换,若小于最早的结束时间,则需要加入一个元素(添加一个新的教室)

四、分数背包问题

       1.问题描述 

        给定背包容量和一些物品,每个物品有重量和价值两个属性。允许只取一个物品的一部分加入背包,求问如何才能使背包装的物品价值最大。

背包问题实质上是一个线性规划问题,可以用单纯形法、椭球法、内点法(后两者均为多项式时间算法)等求解。但在这个问题中,简单的贪心算法就能够求出最优解。

        2.贪心思想:

        既然能够取某个物品的一部分加入背包,则可以先计算出每个物品的单位重量对应的价值再从高到低依次排序,依次放入背包,直至达到背包的总容量(贪心)。

        即先取最划算的,从最划算的依次往下取。

这篇关于贪心算法(活动选择、分数背包问题)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/962173

相关文章

有感FOC算法学习与实现总结

文章目录 基于STM32的有感FOC算法学习与实现总结1 前言2 FOC算法架构3 坐标变换3.1 Clark变换3.2 Park变换3.3 Park反变换 4 SVPWM5 反馈部分5.1 相电流5.2 电角度和转速 6 闭环控制6.1 电流环6.2 速度环6.3 位置环 写在最

Jekyll 解决Jekyll server本地预览文章not found的问题

layout: post tags: [Jekyll] comments: true 执行Jekyll本地浏览器预览指令 bundle exec jekyll serve 进入浏览器输入127.0.0.1:4000,可以正常浏览首页,但是点击文章链接,则会显示404页面,查看控制台显示错误的log,如下: PS D:\work\github\test\_site> bundle e

面试常问的16个C语言问题,你能答上来几个?

大家好,我是小麦。最近不少小伙伴在找工作,这里我给大家分享一下面试中经常会遇到的一些嵌入式C语言问题,你看看能答上来几个呢? 1 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define SEC_YEAR  (365*24*60*60)UL 考察点: #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)懂得预处理器将为你计算常数表达式

太坑了,C标准库缓冲区溢出的问题,该搞清楚了

大家好,我是小麦,今天给大家分享一篇文章。在开发的过程中,如果遇到C标准库缓冲区溢出的问题,那么内心肯定是奔溃的。 下面我们来看看有哪些办法来避免这种情况吧。 C中大多数缓冲区溢出问题可以直接追溯到标准 C 库。最有害的罪魁祸首是不进行自变量检查的、有问题的字符串操作strcpy、strcat、sprintf 和 gets。 大部分程序员仍然会使用这些函数,因为从来没有人教开发人员避免使用它们

关于redis一些问题记录

问题一:启动redis时出现警告,使用下列命令(已解决)       问题二:启动时,需要解决的警告(未解决)       问题三:使用自己的配置文件启动redis时,可能会遇到: Could not connect to Redis at 127.0.0.1:6379: Connection refused 原因:6379 没有断开,使用“exit”后,重新使用redis-c

selenium +java 多个类公用driver问题

问题点:太久没有写selenium代码,居然把driver公用的问题忘记了,即:每写一个测试类,执行过程中都会新建一个窗口,这样应该说是非常不专业的。 大概想了一个方法,虽然看起来也不怎么专业,但感觉能用就很开心了。 解决步骤:                1 创建一个获取获取driver的方法getDriver()                2 创建成员变量,将 getDriver()赋值

关于新版adt22.6.0的相关问题(自己总结)

首先说自己手贱的很,一不小心就更新了adt,导致现在各种问题频出。在网上找到了解决方案  在百度经验《 关于新版ADT创建项目时出现appcompat_v7的问题》!!!这个教程会告诉我们把appcompat_v7作为一个库项目,只有它点击 isLibrary,而你的项目千万不要点击islibrary,否则会在导出的时候出现There is no android project named xx

算法的设计方式

1.贪心算法 贪心算法(又称贪婪算法)是指在对问题求解时,从问题的某一个初始解出发,总是做出在当前看来最好的选择,当达到某算法中的某一步不能再继续前进时,算法停止。这时,就得到了问题的一个解,但不能保证求得的最后解是最优的。也就是说,不从整体最优上加以考虑,它所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题能产生整体最优解或者是整体最优解

冒泡算法及改进(属于交换排序)

冒泡排序(Bubble Sort)是一种交换排序,快速排序也属于一种交换排序。冒泡排序的基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。 假设一共共有 n 个数,则会进行 (n-1)趟比较,由1,2......n-1这么多趟,第一趟进行 (n-1)次比较,.......第n-1趟进行1次比较,故有公式:第i趟 +  第i趟的比较次数 = n       时间复杂度为

Linux删除大文件rm -rf的问题

请几天,我删除系统汇总的大文件,大约100G左右,当我使用rm -rf  xxxx.log删除后,使用df -h发现空间并未释放。 一开始以为是由于磁盘虚拟挂载,导致我删除的文件并不是当前目录的文件。但后来发现并不是。 我在网络上搜索发现都是  要: lsof | grep delete kill -9 xxx 但是我觉得这样不安全。 比如文件被进程锁定,或者有进程一直在向这个文件写数