几个简单的例子
最优装载问题:
给n个物体,第i个物体重量为wi,选择尽量多的物体,使得总重量不超过C。
由于目标是物体的数量尽量多,所以装重的没有装轻的划算。只需把所有物体 按重量从小到大排序,依次选择每个物体,直到装不下为止。这就是一种贪心法,因为每次都是选择能装下的最轻的物体,是一种“只顾眼前”的策略。与动态规划中的01背包问题不同。
部分背包问题:
有n个物体,第i个物体的重量为wi,价值为vi,在总重量不超过C的情 况下让总价值尽量高。每一个物体可以只取走一部分,价值和重量按比例计算
一种直观的贪心策略产生:优先拿价值/重量比最大的,直到重量和正好为C。
与动态规划中的01背包问题不同。
乘船问题:
有n个人, 第i个人重量为wi。每艘船的载重量均为C, 最多乘两个人。用最少的船装载所有人。
考虑最重的一个人i,从剩下的人中选一个可以一起坐船的且重量最大(实际上只要能一起坐就可以了,没必要重量大的)的一起坐船,如果没有满足条件的则i自己一个人坐船,以此类推。
区间上的问题
不相交的区间选择问题:
数轴上有n条开区间(ai;bi),选择尽量多个区间,使得这些 区间两两没有公共点。
首先明确一个问题:如果有两个区间x, y,区间x完全包含y。那么显然选x是不划 算的,因为x和y最多只能选一个,选x还不如选y,这样不仅区间数目不会减少,而且给其他区间留出了更多的位置。这样,我们按照bi从小到大的顺序给区间排序。
贪心策 略是:
一定要选第一个区间,也就是一定要选bi最小的那一个区间。选择了第一个区间之后,可以排除所有与第一个区间相交的区间,然后在剩下的区间中再选择bi最小的区间,因为这样可以给后面留下更大的空间,以此类推。
选点问题:
数轴上有n个闭区间[ai,bi]。取尽量少的点,使得每个区间内都至少有一 个点(不同区间内含的点可以是同一个)
先讨论区间包含的情况,由于小区间被满足时大区间一定也被满足。所以在 区间包含的情况下,大区间不需要考虑。
把所有区间按b从小到大排序(b相同时取a大的),则需要考虑的区间的a值 也是从小到大排好序的(其他区间都不需要考虑)
贪心策略:在第一个区间最右边选点,然后排除被该点标志过所有区间,然后再在剩下的区间的第一个区间最右边选点,重复之前操作。
下图选两个点即可
区间覆盖问题:
数轴上有n个闭区间[ai,bi],选择尽量少的区间覆盖一条指定线 段[s,t]。
本题的突破口仍然是区间包含和排序扫描,不过先要进行一次预处理。每个区间 在[s,t]外的部分都应该预先被切掉,因为它们的存在是毫无意义的。在预处理后,在相互包含的情况下,小区间显然不应该考虑。
按照a从小到大排序。如果区间1的起点不是s,无解(因为其他区间的起点更大, 不可能覆盖到s点),否则选择起点在s的最长区间。选择此区间后[ai,bi],新的起点应 该设置为bi,并且忽略所有区间在bi之前的部分,就像预处理一样,然后选择起点在bi的最长区间,以此类推。
Huffman编码
如下面字母和字母的出现次数:
A(15)、B(20)、C(50)、D(30)、E(18)、F(45)、G(8)
把这些字母存放到二叉树的叶节点中,使得每个字母(出现次数*搜索路径长度)的和最小
先按出现次数从小到大排序:
G(8)、A(15)、E(18)、B(20)、D(30)、F(45)、C(50)
G和A结合成一棵树:
然后再排序:
E(18)、B(20)、G和A构成树的根节点(23)、D(30)、F(45)、C(50)
然后再把E和B结合成树,以此类推,结果为: