第6章 贪心法
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
6.2.3 算法正确性
定理6-1 如果p0/w0p1/w1pn- 1/wn-1 ,则程序6-2求 得的背包问题的解是最优解。
6.3 带时限的作业排序
6.3.1 问题描述
设有一个单机系统、无其它资源限制且每个作业运行相 等时间,不妨假定每个作业运行1个单位时间。 现有n个作业,每个作业都有一个截止期限di>0,di为整 数。如果作业能够在截止期限之内完成,可获得pi>0的收 益。 问题要求得到一种作业调度方案,该方案给出作业的一 个子集和该作业子集的一种排列,使得若按照这种排列 次序调度作业运行,该子集中的每个作业都能如期完成, 并且能够获得最大收益。也就是说这种作业调度是最优 的。
6.1 一般方法
在根据最优量度标准选择分量的过程中,还需要使用 一个可行解判定函数。 贪心,即希望每一步决策都是正确的。 贪心策略并不是从整体上加以考虑的,他只是某种意 义上的局部最优选择,也就是说,每一步决策只是在 当前看来是最优的,因此贪心法不能保证对所有问题 都得到整体最优解。 但对于许多问题,如图的最小代价生成树问题、单源 最短路径问题等,使用精心考虑的选择准则,的确能 产生整体最优解。 贪心法所做出的选择只是当前看似最佳选择,必须进 一步证明该算法最终导致问题的一个整体最优解。
目标函数
max
pi xi
i 0
pi 0 , 0 xi 1 , 0 i n
6.2.2 贪心法求解
例6-1
设有载重能力M=20的背包,3件物品的重量为: (w0,w1,w2)=(18,15,10),物品装入背包的收益 为:(p0,p1,p2)=(25,24,15)。
例6-3 设n=5个作业, 作业的时限为:(d0,d1,d2,d3,d4)=(2,2,1,3,3), 收益为: (p0,p1,p2,p3,p4)=(20,15,10,5,1)。
【程序6-4】带时限的作业排序程序 int JS(int *d, int *x, int n) { //设p0p1pn-1 int k=0; x[0]=0; for (int j=1;j<n;j++){ int r=k; while (r>=0 && d[x[r]]>d[j] && d[x[r]]>r+1) r--; if((r<0||d[x[r]]<=d[j]) && d[j]>r+1){ for (int i=k;i>=r+1;i--) x[i+1]=x[i]; x[r+1]=j; k++; } } return k; }
WPL w k l k
k 1
wenku.baidu.com 6.4.2 贪心法求解
两路合并最佳模式问题的最优量度标准为带权外路径 长度最小。
两路合并最佳模式的贪心算法简述如下:
设W={w0,w1 ,,wn-1}是n个有序文件的 长度;以每个权值作为根结点值,构造n棵只有根 的二叉树; 选择两棵根结点权值最小的树,作为左右子树构造 一棵新二叉树,新树根的权值是两棵子树根的权值 之和; 重复第2步,直到合并成一棵二叉树为止。
6.3.5 作业排序贪心算法
定理6-3提供了一种高效的可行解判定方法。使得在按 最优量度标准,即按作业收益的非增次序选择下一个作业 后,可以有效地判定是否可将该作业加入已生成的部分解 向量X。 具体判定方法:
对任意一个部分解作业子集(x0,x1,…,xk),使X中作业按 时限的非减次序排列,设 =(0, 1,…,k),d 0 ≤ d 1 ≤…≤ d k 是X的这样的排列,为了判定是否为可行的调度 方案,只需对每个作业j 判断d j ≥j+1是否成立。
6.4 最佳合并模式
6.4.1 问题描述
两路合并外排序算法通过反复执行将两个有序子文件 合并成一个有序文件的操作,最终将n个长度不等的 有序子文件合并成一个有序文件。 合并n个有序子文件成为一个有序文件的合并过程可 以有多种方式,称为合并模式。
6.4.1 问题描述
每执行一次合并需将两个有序文件的全部记录依次从 外存读入内存,还需将合并后的新文件写入外存。 采用不同的两两合并方案,完成合并所需进行外存读 /写的记录总数不同(社队一个记录的读和些合计为 一次)。 在整个合并过程中,需从外存读写的记录数最少的合 并 方 案 称 为 最 佳 合 并 模 式 ( optimal merge pattern)。 可以用合并树描述一种合并模式。
为了判断作业j是否允许添加到部分解向量中,具 体做法是:
将作业j按时限的非减次序插入向量(x[0], x[1], x[2],…, x[k])中的某个位臵,是的插入作业j后,由 k+1个分量组成的部分解向量仍按时限的非减次序排列。 设j被插于下标r+1处。则作业x[r+1]…x[k]在向量 中的位臵都必须依次后移一位,形成一个新的部分解向 量。 为了保证在添加作业j后的作业子集仍能够构成可行解, 必须满足下列两点要求: d[x[j]]>j+1, r+1 ≤ j ≤ k d[j]>r+1,
6.2 背包问题
6.2.1 问题描述
已知一个载重为M的背包和n件物品,第i件物品的 重量为 wi,如果将第i件物品全部装入背包,将有 收益pi,这里,wi>0,pi>0,0≤i<n。 所谓背包问题是指求一种最佳装载方案,使得收益 最大。 背包问题是现实世界一个常见的最优化问题。
6.2.1 问题描述
6.3.6 一种改进算法
本小节将介绍一种带时限作业排序的快速算法,它 采用不同于前者的可行解判定方法,可使算法的时 间从(n2)减少到接近O(n)。
例6-3 设n=5个作业, 作业的时限为:(d0,d1,d2,d3,d4)=(2,2,1,3,3), 收益为: (p0,p1,p2,p3,p4)=(20,15,10,5,1)。
6.1 一般方法
6.1 一般方法
最优化问题(optimization problems)
问题给定某些约束条件(constraint),满足这些约束 条件的问题解称为可行解(feasible solution)。通 常满足约束条件的解不是惟一的。
目标函数(objective function)
6.4.1 问题描述
例6-4 设有5个有序子文件(F1,F2,F3,F4,F5),其长度分别 为(20,30,30,10,5)。现通过两两合并将其合并成一个 有序文件。
6.4.1 问题描述
两路合并树表达的合并方案确定了合并排序过程中所 需读/写的记录总数,这个量正式该两路合并树的带权 外路径长度。 带权外路径长度是针对扩充二叉树而言的。 扩充二叉树(extended binary tree)中除叶子结点 外,其余结点都必须有两个孩子。 扩充二叉树的带权外路径长度(weighted external path length)定义为: m
template<class T> void Knapsack<T>::GreedyKnapsack(float* x) { //前置条件:w[i]已按p[i]/w[i]的非增次序排列 float u=m; for (int i=0;i<n;i++) x[i]=0; for (i=0;i<n;i++) { if (w[i]>u) break; x[i]=1.0; u=u-w[i]; } if (i<=n) x[i]=u/w[i]; }
6.1 一般方法
贪心法是通过分步决策(stepwise decision)的方法来 求解问题的。 贪心法每一步上用作决策依据的选择准则被称为最优 量度标准(optimization criterion)或称为贪心准则 (greedy criterion),也称贪心选择性质。 在初始状态下,解向量为空。使用最优量度标准,一 次选择一个分量,逐步形成解向量(x0,x1,x2,…,xn-1)。 算法过程中生成的向量(x0,x1,x2,…,xk)(k<n)称为 部分解向量,或部分向量。
6.2.2 贪心法求解
背包问题
背包问题的解可以表示成一个n-元组:X=(x0,x1,,xn-1),0xi1, 0i<n,每个xi是第i件物品装入背包中的部分。
判定可行解的约束条件是:
n1 i 0
wi xi M
n1
wi 0 , 0 xi 1 , 0 i n
6.3.3 算法正确性
定理6-2 程序6-2的贪心算法对于带时限作业排序问题将得 到最优解。
6.3.4 可行性判定
定理6-3
X=(x0,x1,…,xk)是k个作业的集合,=(0, 1,…,k)是X 的一种特定排列,它使得,其中, 是作业j的时限。X是一个可行解当且仅当X中 的作业能够按次序调度而不会有作业超期。
6.3.2 贪心法求解
例6-2 设有4个作业,每个作业的时限为 (d0,d1,d2,d3)=(2,1,2,1),收益为 (p0,p1,p2,p3)=(100,10,15,27)。
【程序6-3】带时限作业排序的贪心算法 void GreedyJob(int d[], Set X, int n) { //前臵条件:p0p1,…,pn-1 X={0}; for (int i=1;i<n;i++) if ( 集合 X{i} 中作业都能在给定时限内完成) X=X{i}; }
按物品重量的非降次序选择物品 以重量为度量标准,让背包载重慢慢消耗
试验标准3:
选择使单位重量收益最大的物品装入背包,即 按pi/pw的非增次序选取物品。
【程序6-2】背包问题的贪心算法 template<class T> class Knapsack { public: Knapsack(int mSize,float cap,float *wei,T *prof); void GreedyKnapsack(float* x); …… private: float m,*w; T *p; int n; };
算法分析与设计
鲁 敏(讲师) 中南财经政法大学信息学院 ulula@yahoo.cn 2013年7月22日 lumiousy@yahoo.com.cn
第6章 贪心法
6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 一般方法 背包问题 带时限的作业排序 最佳合并模式 最小代价生成树 单源最短路径 磁带最优存储 贪心法的基本要素
两类背包问题:
如果每一件物品不能分割,只能作为整体或者装入背包, 或者不装入,称为 0/1背包问题; 如果物品是可以分割的,也就是允许将其中的一部分装 入背包为一般背包问题或简称背包问题。
0/1背包问题看似简单,却无法用贪心法求得它的 最优解,而只能的到它的近似解。 本节讨论一般背包问题(背包问题)。
6.2.2 贪心法求解
用贪心法求解,找出最优量度标准是至关重 要的。 如何得到最优量度标准并没有现成的方法。 一般需要根据现有的知识和经验,通过猜测 形成一些选择准则,并进行测试找出规律。
6.2.2 贪心法求解
试验标准1:
选取目标函数作为度量标准 不考虑重量,收益优先
试验标准2:
为了衡量可行解的好坏,问题还给出了某个数值函数,称 为目标函数。
最优解(optimal solution)
使目标函数取最大(或最小)值的可行解称为最优解。
6.1 一般方法
穷举法(brute force approach)
假定所有的可行解都属于一个候选解集,若该 候选解集是有限集,从理论上讲可以用穷举法。 一一考察候选解集中的每一个,检查它是否满 足约束条件。 若某个候选解能满足约束条件,便是可行解。 通过衡量可行解,找到最优解。 当候选解集十分庞大时,这种方法费时而且不 经济,当候选解集为无穷集合时,无法求解。
6.1 一般方法
【程序6-1】贪心法 SolutionType Greedy(SType a[],int n) { SolutionType solution=; for(int i=0;i<n;i++){ SType x=Select(a); if (Feasiable(solution, x)) solution=Union(solution, x); } return solution; }