第16章 贪心算法

16.1 活动选择问题

问题:假设有一个n个活动的集合S=a1,a2,...,anS={a_1,a_2,...,a_n},这些活动使用同一个资源,而这个资源在某个时刻只能供一个活动使用。每个活动都有一个开始时间sis_i和一个结束时间fif_i。若si≥fis_i\geq f_i或sj≥fis_j\geq f_i,则aia_i和aja_j是兼容的。在活动选择问题中,我们希望选出一个最大兼容活动集。假设活动已按结束时间的单调递增顺序排序。

1、动态规划法

令SijS_{ij}表示在aia_i结束之后开始。且在aja_j开始之前结束的那些活动的集合,用c[i,j]c[i,j]表示集合SijS_{ij}的最优解的大小,故有

c[i,j]=0,ifSij=ϕc[i,j]=maxak∈Sijc[i,k]+c[h,j]+1,ifSij≠ϕ

c[i,j]=0, if S_{ij}=\phi\\ c[i,j]=\max_{a_k\in S_{ij}}{c[i,k]+c[h,j]+1}, if S_{ij}\neq\phi

2、贪心选择

定理:考虑任意非空子问题SkS_k,令ama_m是SkS_k中结束时间最早的活动,则ama_m在SkS_k的某个最大兼容活动子集中。
证明:令AkA_k是SkS_k的一个最大兼容子集,且aja_j是AkA_k中结束时间最早的活动。
若aj=ama_j=a_m,即证。
若aj≠ama_j\neq a_m,将AkA_k中的aja_j替换为ama_m,因为fm≤fjf_m\leq f_j,则还是兼容的,数目不变,故替换后的也是SkS_k的一个最大兼容活动子集,且包含ama_m。
- 递归贪心算法
为方便初始化,添加一个虚拟活动a0a_0,其结束时间f0=0f_0=0

public List<Integer> RECURSIV_ACTIVITY_SELECTOR(int[] s,int[] f,int k,int n){int m = k + 1;while(m<=n && s[m]<=f[k])m++;List<Integer> res = new ArrayList<>();if(m<=n)return res.add(m).addAll(RECURSIV_ACTIVITY_SELECTOR(int[] s,int []f,int k,int n))elsereturn res;
}
  • 迭代贪心算法
public List<Integer> GREED_ACTIVITY_SELECTOR(int[] s,int[] f){int n = s.length - 1; //去掉虚拟活动List<Integer> res = new ArrayList<>();res.add(1);int k = 1;for(int i = 2; i<=n; i++){if(s[m]>=f[k]){res.add(m);k = m;}}return res;
}

16.2 贪心算法原理

一般地,我们按如下步骤设计贪心算法:
1. 将最优化问题转化为这样的形式:对其做出一次选择后,只剩下一个子问题需要求解。
2. 证明做出贪心选择后,原问题总是存在最优解,即贪心选择总是安全的。
3. 证明做出贪心选择后,剩余的子问题满足性质:其最优解与贪心选择组合即可得到原问题的最优解,这样就得到了最优子结构。

贪心对动态规划

0-1背包问题:动态规划

分数背包问题:贪心

/*** @param m 表示背包的最大容量* @param n 表示商品个数* @param w 表示商品重量数组* @param p 表示商品价值数组*/
public static int[][] Package1(int m, int n, int[] w, int[] p) {//c[i][v]表示前i件物品恰放入一个重量为m的背包可以获得的最大价值int c[][] = new int[n + 1][m + 1];for (int i = 0; i < n + 1; i++)c[i][0] = 0;for (int j = 0; j < m + 1; j++)c[0][j] = 0;for (int i = 1; i < n + 1; i++) {for (int j = 1; j < m + 1; j++) {//当物品为i件重量为j时,如果第i件的重量(w[i-1])小于重量j时,c[i][j]为下列两种情况之一://(1)物品i不放入背包中,所以c[i][j]为c[i-1][j]的值//(2)物品i放入背包中,则背包剩余重量为j-w[i-1],所以c[i][j]为c[i-1][j-w[i-1]]的值加上当前物品i的价值if (w[i - 1] <= j) {if (c[i - 1][j] < (c[i - 1][j - w[i - 1]] + p[i - 1]))c[i][j] = c[i - 1][j - w[i - 1]] + p[i - 1];elsec[i][j] = c[i - 1][j];} elsec[i][j] = c[i - 1][j];}}return c;
}
//用一维数组存储
public static int Package2(int m, int n, int[] w, int[] p) {int[] f = new int[m + 1];for (int i = 1; i < f.length; i++)    //必装满则f[0]=0,f[1...m]都初始化为无穷小f[i] = Integer.MIN_VALUE;for (int i = 0; i < n; i++) {for (int j = f.length - 1; j >= w[i]; j--) {f[j] = Math.max(f[j], f[j - w[i]] + p[i]);}}return f[m];
}

在具体运用时,可以首先假设全部物品装进背包是否超载,若不超载则直接输出最优解。有一次某公司一道笔试题就是这样,直接上dq就超时gg了=。=

16.3 赫夫曼编码

赫夫曼编码用于压缩数据,根据每个字符的出现频率构造最优二进制表示。
前缀码:没有任何码字是其他码字的前缀。
构造赫夫曼编码,使用一个以属性freq为关键字的最小优先队列Q。

HUFFMAN(C)
n = C.length
Q = C
for i =1 to n-1allocate a new node zz.left = x = EXTRACT-MIN(Q)z.right = y = EXTRACT-MIN(Q)z.freq = x.freq + y.freqINSERT(Q,z)
return EXTRACT-MIN(Q) //return the root of the tree

定理:过程HUFFMAN会生成一个最优前缀码。

《算法导论》第16章 贪心算法 个人笔记相关推荐

  1. 《算法导论》学习总结 — 21.第16章 贪心算法(1) 基础入门1

    建议先看看前言:http://www.wutianqi.com/?p=2298 连载总目录:http://www.wutianqi.com/?p=2403 说到贪心算法,避免不了于DP对比,所以前面的 ...

  2. 【算法导论】学习笔记——第16章 贪心算法

    贪心算法是使做出的选择看起来都是当前最佳的,期望通过所做的局部最优选择来产生一个全局最优解.其实,这个定义旨在说明贪心算法必须伴随做出最优选择,如moving table,我们选择最大重叠数等等.当然 ...

  3. 算法导论第16章练习题 16.1-4

    16.1-4 假设有一组活动,我们需要将它们安排到一些教室,任意活动都可以在任意教室进行.我们希望使用最少的教室来完成活动.设计一个高效的贪心算法,求每个活动应该在哪个教室来进行. (这个问题也被称为 ...

  4. 《算法导论3rd第一章》算法在计算中的作用

    前言 什么是算法?为什么算法值得研究?算法的作用是什么 算法 算法就是任何良定义的计算过程,该过程取某个值或值的集合作为输入并产生某个值或值的集合做为输出.即就是把输入转换成输出的计算步骤的一个序列. ...

  5. 算法设计与分析第3章 贪心算法

    第4章 贪心算法 贪心算法总是作出在当前看来最好的选择.也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择. 贪心算法的基本要素 1.贪心选择性质 所谓贪心选择性质是指所 ...

  6. 位向量(bit vector)(算法导论第十一章11.1-2)

    位向量(bit vector) 位向量(bit vector)是一个仅包含0和1的数组.长度为m的位向量所占空间要比包含m个指针的数组少得多.说明如何用一个位向量来表示一个包含不同元素(无卫星数据)的 ...

  7. 假设一动态集合S用一个长度为m的直接寻址表T来表示。请给出一个查找S中最大元素的过程。(算法导论第十一章11.1-1)

    假设一动态集合S用一个长度为m的直接寻址表T来表示.请给出一个查找S中最大元素的过程.你所给的过程在最坏情况下的运行时间是多少. (算法导论第十一章11.1-1) #include "Key ...

  8. 【Java数据结构与算法】第十九章 贪心算法、Prim算法和Kruskal算法

    第十九章 贪心算法.Prim算法和Kruskal算法 文章目录 第十九章 贪心算法.Prim算法和Kruskal算法 一.贪心算法 1.介绍 2.支付问题 二.Prim算法 1.最小生成树 2.介绍 ...

  9. 第四十一章 贪心算法——排序不等式

    第四十一章 贪心算法--排序不等式 一.题目信息 二.排序不等式 1.算法内容 2.算法证明 3.思路分析 三.代码实现 一.题目信息 二.排序不等式 1.算法内容 2.算法证明 3.思路分析 这道题 ...

最新文章

  1. MS IME 2007输入法
  2. java-List集合的源码分析(数据结构方面,源码注释方面),迭代器快速失败机制
  3. Linux中的防火墙----iptables
  4. 数据结构之基于Java的链接栈实现
  5. loj10147. 「一本通 5.1 例 1」石子合并
  6. 电商大促特辑:蘑菇街致美丽新世界的架构礼
  7. 一个前端博客(7)——事件绑定和移除事件
  8. 如何利用RPLIDAR A2进行多点触摸应用
  9. Layui 表格分页控件
  10. Riverbed宣布收购领先的Wi-Fi网络提供商Xirrus
  11. 【办公应用软件】万彩办公大师教程丨屏幕OCR工具的应用
  12. 李宏毅机器学习课程自测练习题
  13. 装linux系统的工具箱,PE,Dos工具箱,自动安装linux的U盘制作
  14. Win11,cmd闪退的一种解决思路
  15. java的SSM框架的优点有哪些
  16. 人脸识别门禁为何倍受青睐?
  17. word题注“一-1”改为“1-1”
  18. 1.3 电功率和能量
  19. Flash新手教程:打造拟真生态水族鱼缸-添加动画效果
  20. Ubuntu18.04 系统重装 若干问题及解决方法

热门文章

  1. 配置 Vue 实例( 选项 )
  2. 基于 xterm + websocket + vue 实现网页版终端 terminal
  3. 关于移动端使用position:fixed/absolute出现随屏幕滚动情况
  4. 留数定理构造围道计算实积分类型大全
  5. 拨乱反正:MyISAM中key_buffer_size的设置
  6. Eclipse运行tomcat出现错误“An incompatible version [1.1.33] of the APR based。。。 ”问题的解决
  7. 怎样将网页保存为html,如何将网页保存为书签
  8. jeecg-boot实现分布式定时任务
  9. 胖子和瘦子谁更怕冷?
  10. BZOJ1202 狡猾的商人 (Floyd)