关于贪心算法的经典问题(算法效率 or 动态规划)
如题,贪心算法隶属于提高算法效率的方法,也常与动态规划的思路相挂钩或一同出现。下面介绍几个经典贪心问题。(参考自刘汝佳著《算法竞赛入门经典》)。
P.S.下文皆是我一个字一个字敲出来的,绝对“童叟无欺”,哈哈。(。⌒∇⌒) 耗费了我的很多时间,所以——希望对大家有帮助啊~ (=^‸^=)
一、背包相关问题
1.最优装载问题:给出N个物体,有一定重量。请选择尽量多的物体,使总重量不超过C。
解法:只关心数量多,便把重量从小到大排序,依次选,直到装不下。
2.部分背包问题:给出N个物体,有一定重量和价值。请选择一些物体的一部分使在总重量不超过C的条件下总价值最大。
解法:关心总价值大,物体可取部分,便优先取单位重量价值较大的物体。
3.乘船问题:有N个人,有一定重量。每艘船的最大载重量均为C,且最多载2人。请用最少的船装载所有人。
解法:关心数量少,要尽量使每艘船的实际载重量尽量接近于最大载重量。便把重量从小到大排序,每艘船依次先载一个人,再载重量最接近船的剩余可载重量的人。这样可以使眼前的消费(剩余载重量)最少。
实现:用2个变量 l , r 分别从两头往中间移动,l 和 r 可共乘一艘船,或 r 自己乘一艘船。
二、区间相关问题
1.选择不相交区间:数轴上有N个开区间(Li,Ri),请选择尽量多个区间,并保证这些区间两两没有公共点。
解法:先把这些区间按找 Ri 从小到大的顺序排序,再对按序排列的每2个区间A,B分情况讨论:(1)A被B包含,选A最优;(2)A右边的一部分与B左边的一部分相交,选A最优,因为选A比B减少了与后面区间相交的可能性;(3)A、B不相交,便2个都选。总的来说就是排序后,从左到右选第一个没有与前面已选的区间相交的区间。O(n)。
拓展:那么如果可以一共覆盖两次,那该怎么选? ——也就是【bzoj3433】{Usaco2014 Jan}Recording the Moolympics(算法效率--贪心)。
2.区间选点问题:数轴上有N个闭区间[Li,Ri],请选择尽量少的点,使得每个区间内都至少有一个点。
解法:同样地先把这些区间按找 Ri 从小到大的顺序排序,再分类讨论:(1)A被B包含,不需理会B; P.S.没有明显的思路就暂时不推到具体选哪一个点 (≡・ x ・≡) (2)A右边的一部分与B左边的一部分相交,当拓展到3个或以上都有一部分重叠时,肯定选第一个区间的右端点,以使这个点处于更多的区间内;(3)A、B不相交,便各自随意填一个点。总的来说就是排序后,从左到右选第一个没有与前面已选的区间相交的区间的右端点。O(n)。
3.区间覆盖问题问题:数轴上有N个闭区间[Li,Ri],选择尽量少的区间覆盖一条指定线段[s,t]。
实现:先预处理一遍把线段外的区间的所有部分去掉,然后按 Li 从小到大的顺序排序,选当前 Ri 最大的。再选剩下的起点在刚选完的区间的右端点之前的右端点最右的区间。O(n)。
三、Huffman编码
最优编码问题:给出N个字符的频率 ci ,给每个字符赋予一个01编码串,使得任意一个字符的编码不是另一个字符编码的前缀,而且编码后总长度(每个字符的频率与编码长度乘积的总和)尽量小。
解法:
Step 1.从01串,转换为构造一棵最优的编码树,左孩子是0,右孩子是1。而由于是编码,不能其中一个是另一个的前缀,便所有的字符都是叶子结点,不存在任一个是另一个的祖先,且要最优便不会叶子结点不是一个编码。。。
Step 2.转换问题之后便用Huffman算法就可以了。∠※ 把每个字符看作一个单结点子树放在一个树集合中,每棵子树的权值等于相应字符的频率。每次取权值最小的两棵子树合并成一棵新树,并重新放到集合中。新树的权值等于两棵子树权值之和。可以通过2个结论证明其正确性:1.贪心选择性质,使得第一步贪心法选择保留最优解。设x和y是频率最小的两个字符,则存在前缀码使得x和y具有相同码长,且仅有最后一位编码不同;2.最优子结构性质,使得原问题的最优解包含子问题的最优解。设 x 和 y 是有相同父亲结点 z 的两个叶子结点,那么把它们两个去掉,而留下 z 的最优编码树不会变。即——通过确定“”就知道这个算法是正确的啦。
实现:先按照频率把所有字符排序为一个队列P,再建一个队列Q存新的结点。先合并P最前面的2个结点后把新结点放在另一个队列Q,删除这2个结点。由于两个队列都是有序的,就可以接着从P最前面的2个结点后Q的前2个结点中选出2个频率最小的结点合并,新结点同样放在另一个队列,知道队列P为空。所以总时间复杂度是O(n log n+n)≈O(n log n)。我之前打过一道运用了这个知识点的题——【uva 10954】Add All(算法效率--Huffman编码+优先队列)
关于贪心算法的经典问题(算法效率 or 动态规划)的更多相关文章
- 【十大经典数据挖掘算法】AdaBoost
[十大经典数据挖掘算法]系列 C4.5 K-Means SVM Apriori EM PageRank AdaBoost kNN Naïve Bayes CART 1. 集成学习 集成学习(ensem ...
- 基于python的七种经典排序算法
参考书目:<大话数据结构> 一.排序的基本概念和分类 所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作.排序算法,就是如何使得记录按照要求排列的方法. ...
- 【最全】经典排序算法(C语言)
算法复杂度比较: 算法分类 一.直接插入排序 一个插入排序是另一种简单排序,它的思路是:每次从未排好的序列中选出第一个元素插入到已排好的序列中. 它的算法步骤可以大致归纳如下: 从未排好的序列中拿出首 ...
- C++经典排序算法总结
转发请注明出处:https://www.cnblogs.com/fnlingnzb-learner/p/9374732.html 最近在研究一些经常用到的东西想把它们做一个汇总,想了想用到最多的应该是 ...
- c++经典排序算法全集(转)
C++排序算法全集 排序算法是一种基本并且常用的算法.由于实际工作中处理的数量巨大,所以排序算法对算法本身的速度要求很高. 一.简单排序算法 由于程序比较简单,所以没有加什么注释.所有的程序都给出了完 ...
- 基于python的七种经典排序算法(转)
一.排序的基本概念和分类 所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作.排序算法,就是如何使得记录按照要求排列的方法. 排序的稳定性:经过某种排序后,如果两个 ...
- JavaScript 数据结构与算法之美 - 十大经典排序算法汇总(图文并茂)
1. 前言 算法为王. 想学好前端,先练好内功,内功不行,就算招式练的再花哨,终究成不了高手:只有内功深厚者,前端之路才会走得更远. 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 ...
- 一文搞定十大经典排序算法(Java实现)
本文总结十大经典排序算法及变形,并提供Java实现. 参考文章: 十大经典排序算法总结(Java语言实现) 快速排序算法—左右指针法,挖坑法,前后指针法,递归和非递归 快速排序及优化(三路划分等) 一 ...
- python 经典排序算法
python 经典排序算法 排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存.常见的内部排序算 ...
随机推荐
- SonarQube学习(五)- SonarQube之自定义规则使用
一.前言 古人云:"欲速则不达",最近真的是深有体会.学习也是如此,不是一件着急的事,越是着急越不会. 就拿SonarQube来说吧,去年年末就想学来着,但是想着想着就搁置了,有时 ...
- 【SpringBoot1.x】SpringBoot1.x 日志
SpringBoot1.x 日志 日志框架 市面上有很多日志框架,一个日志框架一般包括抽象层和实现. SpringBoot,它的底层是 Spring,而 Spring 框架默认是用 JCL(java. ...
- RecyclerView 源码分析(一) —— 绘制流程解析
概述 对于 RecyclerView 是那么熟悉又那么陌生.熟悉是因为作为一名 Android 开发者,RecyclerView 是经常会在项目里面用到的,陌生是因为只是知道怎么用,但是却不知道 Re ...
- 【Java】Java关键字、含义
Java关键字 来自 Java 核心技术卷I 基础知识(原书第10 版)/( 美)凯S 霍斯特曼(Cay S . Horstmann )著: 周立新等译一北京:机械工业出版社, 2016 . 8 Ja ...
- 计算起始车站车费问题-JavaScript数组对象写法
计算起始站车费 题目:深圳--60--广州--50-虎门--40- -中山--36-珠海一34-澳门一89一香港以上车票费用计算,如坐车深圳到广州60元,广州到虎门50元,深圳到虎门就是60+50-1 ...
- java中如何踢人下线?封禁某个账号后使其会话立即掉线!
需求场景 封禁账号是一个比较常见的业务需求,尤其是在论坛.社区类型的项目中,当出现了违规用户时我们需要将其账号立即封禁. 常规的设计思路是:在设计用户表时增加一个状态字段,例如:status,其值为1 ...
- 微信登录4-开发回调URL
一.准备 1.引入pom依赖 在要使用HttpClient的项目中加入依赖 <!--httpclient--> <dependency> <groupId>org. ...
- Flask中的g到底是个什么鬼?
g到底是个什么鬼? 在一次请求请求的周期,可以在g中设置值,在本次的请求周期中都可以读取或复制. 相当于是一次请求周期的全局变量. from flask import Flask,g app = Fl ...
- Flask的配置文件加载两种方式
配置文件 1 基于全局变量 2 基于类的方式 配置文件的加载需要将配合文件的相对路径添加到app.config.from_object("文件路径"),类的方式也是一样,需要将类的 ...
- 彻底解决小程序无法触发SESSION问题
一.首先找到第一次发起网络请求的地址,将服务器返回set-cookie当全局变量存储起来 wx.request({ ...... success: function(res) { console.lo ...