算法设计与分析 贪心算法

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

单位价值4元
=¥60+100
背包容量:50公斤
20
背包问题具有贪心选择特性
贪心算法
物品1 10公斤,价值60元
单位价值6元
物品3
单位价值5元
20公斤 20公斤 10公斤
物品2 20公斤,价值100元
物品2 物品1
物品3 30公斤,价值120元
单位价值4元
=¥60+100+80
背包容量:50公斤
21
2
贪心算法


顾名思义,贪心算法总是作出在当前看来最好 的选择。也就是说贪心算法并不从整体最优考 虑,它所作出的选择只是在某种意义上的局部 最优选择。当然,希望贪心算法得到的最终结 果也是整体最优的。 虽然贪心算法不能对所有问题都得到整体最优 解,但对许多问题它能产生整体最优解。如单 源最短路经问题、最小生成树问题等。在一些 情况下,即使贪心算法不能得到整体最优解, 其最终结果却是最优解的很好近似。
3
例:用贪心法求解付款问题。
假设有面值为5元、2元、1元、5角、2角、1角的 货币,需要找给顾客4元6角现金,如何使付出的 货币的数量最少。 首先选出1张面值不超过4元6角的最大面值的货币,
即2元,再选出1张面值不超过2元6角的最大面值
的货币,即2元,再选出1张面值不超过6角的最大 面值的货币,即5角,再选出1张面值不超过1角的 最大面值的货币,即1角,总共付出4张货币。
则有:
n n n

i 1
wk xk z i pi p1 xi pi w1 i k 1

x p
i i k
i
P
( 1)若等式成立,则Z也为最优解,继续同样过程,可使z1 1, 或 0, Z是以贪心算法开始的最优解。 (2)若大于成立,与X为最优解矛盾,不成立。 故总存在以贪心算法开始的最优解。
23
背包问题的贪心算法
float knapsack(float c,float w[], float v[],float x[],int n) { ITEMTYPE d[n]; for (int i = 0; i < n; i++) d[i] <= (w[i],v[i],i); mergeSort(d); //按照单价高低排序 D[ ]: int i; 算法knapsack的 float opt=0; w v 主要计算时间是 for (i=0;i<n;i++) x[i]=0; 10 60 将各种物品依其 for (i=0;i<n;i++) { //贪心选择 if (d[i].w>c) break; 单位重量的价值 20 100 x[d[i].i]=1; opt+=d[i].v; c-=d[i].w; 从大到小排序。 } 30 120 if (c>0&& i<n) { //零碎空间 因此,算法的计 x[d[i].i] = c/d[i].w; opt += x[d[i].i]*d[i].v; 算时间上界为O } return opt; (nlogn)。 } x 1 1
在付款问题每一步的贪心选择中,在不超 过应付款金额的条件下,只选择面值最大 的货币,而不去考虑在后面看来这种选择 是否合理,而且它还不会改变决定:一旦 选出了一张货币,就永远选定。 付款问题的贪心选择策略是尽可能使付出 的货币最快地满足支付要求,其目的是使 付出的货币张数最慢地增加,这正体现了 贪心法的设计思想。
与假设矛盾!
27
(2)活动安排具有贪心选择特性
令子问题Sij≠Ø 且a1为子问题Sij中具有最
早完成时间的任务,则a1一定包含在子 问题Sij中某个任务相互兼容的最大子集 中。 结论:具有贪心选择特性。
28
‫ ‫‬证明:
‫ ‫‬假设子问题Sij的最优解为Aij,其中的任
26
(1)活动安排具有最优子结构性质
Sij表示第i个任务结束之后,第j个任务开始之 前的任务集合。 假设子问题Sij的最优解集合为Aij且包含任务ak, 则在最优解集合里的子问题Sik的解Aik以及子 问题Skj的解Akj也一定是最优的。 证明:
假设子问题Sik存在一个更优的解A’ik,则
|A'ik|+1+|Akj|>|Aik|+1+|Akj|=|Aij|
和一个结束时间fi,且si <fi。如果选择了活动i,
则它在半开时间区间[si, fi)内占用资源。若区
间[si, fi)与区间[sj, fj)不相交,则称活动i
与活动j是相容的。
25
各活动占用资源情况
按照每个活动完成时间的顺序排列
假设按照11个活动的结束时间的非 减序排列如下:
i s[i] f[i] 1 1 4 2 3 5 3 0 6 4 5 7 5 3 8 6 5 9 7 6 10 8 8 11 9 8 12 10 2 13 11 12 14
与0-1背包问题类似,所不同的是在选择物品i装入背 包时,可以选择物品i的一部分,而不一定要全部装入 背包,1≤i≤n。
15
0-1背包与背包问题都具有最优子结构
已知背包最大承载重量为C,共有n个物品, 每个物品的重量分别为Wi(i=1,2,...,n),价值 为Vi(i=1,2,...n)。
证明:

0-1背包问题:
给定n种物品和一个背包。物品i的重量是Wi,其价值为Vi, 背包最大承载重量为C。应如何选择装入背包的物品,使 得装入背包中物品的总价值最大?
在选择装入背包的物品时,对每种物品i只有2种选择, 即装入背包或不装入背包。不能将物品i装入背包多 次,也不能只装入部分的物品i。
来自百度文库背包问题:
假设第k个物品是最优解中的一个物品,则
从中拿出Wk对应的物品后所对应的解一定是 其余n-1个物品、装入背包最大承载重量为 C-Wk的最优解,否则与假设矛盾。
16
0-1背包问题不具有贪心选择性质。
原因是无法保证能够将背包装满, 而所剩空间将会降低总价值。
背包问题具有贪心选择性质。
17
背包问题具有贪心选择性质: 最优解分析:
typedef struct { float w,v; int i; } ITEMTYPE;
i 1 2 3
单价 6 5 4
2/3
24
4.2 活动安排问题
设有n个活动的集合E={1,2,…,n},其中每个活
动都要求使用同一资源,如演讲会场等,而在
同一时间内只有一个活动能使用这一资源。每
个活动i都有一个要求使用该资源的起始时间si
法求解的关键特征。
11
3.贪心算法与动态规划算法的差异
共同点:求解的问题都具有最优子结构性质
差异点:动态规划算法通常以自底向上的方式
解各子问题,而贪心算法则通常以自顶向下的
方式进行,以迭代的方式作出相继的贪心选择,
每做一次贪心选择就将所求问题简化为规模更 小的子问题。
12
贪心选择性质:在动态规划算法中,每步所作的选择往往 依赖于相关子问题的解。因而只有在解出相关子问题后, 才能作出选择。而在贪心算法中,仅在当前状态下作出最 好选择,即局部最优选择,然后再去解作出这个选择后产 生的相应的子问题。贪心算法所作的贪心选择可以依赖于 以往所作过的选择,但决不依赖于将来所作的选择,也不 依赖于子问题的解。
设物体1,物体2,…,物体n已按价值重量比的降序 排序。 贪心选择性质:
设X={x1,x2,…,xn}是背包问题的一个最优解。 令k=min{i|xi∈0,1≤i≤n}, 若k=1,则X是以贪心算法开始的最优解。
若k‡1,令Z中zk=0,z1=wkxk/w1 ,zi=xi (1≤i≤n,i‡k,i‡1)
贪心算法的基本步骤
从问题的某个初始解出发 采用循环语句,当可以向求解目标前 进一步时,就根据局部最优策略,得 到一个部分解,缩小问题的范围或规 模 将所有部分解综合起来,得到问题的 最终解

4.1 贪心算法的基本要素
利用贪心算法求解最优解的两个前提条件: 贪心选择性质和最优子结构性质。
1.贪心选择性质
所谓贪心选择性质是指所求问题的整体最优解 可以通过一系列局部最优的选择,即贪心选择 来达到。这是利用贪心算法求解最优解的第一 个基本要素,也是贪心算法与动态规划算法的 主要区别。
10
2.最优子结构性质
当一个问题的最优解包含其子问题的最优解时,
称此问题具有最优子结构性质。问题的最优子
结构性质是该问题可用动态规划算法或贪心算
第 4章
贪心算法
4.1 贪心算法的基本要素 4.2 活动安排问题 4.3 最优装载 4.4 单源最短路径 4.5 哈夫曼编码
4.6 多机调度问题
1
学习要点
理解贪心算法的概念。 掌握贪心算法的基本要素 (1)最优子结构性质 (2)贪心选择性质 理解贪心算法与动态规划算法的差异 理解贪心算法的一般理论 通过应用范例学习贪心设计策略。 (1)活动安排问题。 (2)最优装载问题。 (3)哈夫曼编码。 (4)单源最短路径。 (5)最小生成树。 (6)多机调度问题。
用贪心算法解背包问题的基本步骤:
1.计算每种物品单位重量的价值Vi/Wi; 2.按照单位重量的价值从高到低的顺序排序; 3.依据贪心选择策略,按照单位价值从高到低 的顺序,依次将尽可能多的物品装入背包中。 直到背包装满为止。
是否可以将物品装入背包的条件是:
有空间
22
背包问题的贪心算法
void knapsack(float c,float w[], float v[],float x[],int n) { 将各种物品依其单位重量的价值从高到低排序 初始化 x[i]=0; for (i=0;i<n;i++) { //贪心选择 if (不能放) break; 放入背包中 } w[i]重量 if (背包没满&&还有物品) { v[i]单位价值 装满; } x[i]结果 return opt; }
7
贪心算法框架
Greedy(A,n) { //A为输入集合 solution = Ø; // 解空间初始化为空 for (i = 1; i <=n; i++) { //对每个输入进行检测 x = select(A); // 选择一个输入 if (feasible(solution,x)) // 如果可行
因此,动态规划算法通常以自底向上的方式解各子问题 ,而贪心算法则通常以自顶向下的方式进行,以迭代的方 式作出相继的贪心选择,每作一次贪心选择就将所求问题 简化为一个规模更小的子问题。

贪心算法中作出的每步贪心决策都无法改变, 因为贪心策略是由上一步的最优解推导下一步 的最优解,而上一部之前的最优解则不作保留 ,贪心算法每一步的最优解一定包含上一步的 最优解。 动态规划算法中全局最优解中一定包含某个局 部最优解,但不一定包含前一个局部最优解, 因此需要记录之前的所有最优解。
说明:证明贪心选择性质的一般方法是:首先假设问题的 一个整体最优解,并证明可修改这个最优解,使其以贪心 算法开始。
0-1背包问题不具有贪心选择特性
贪心算法
物品1 10公斤,价值60元
最优解
单位价值6元
物品3
物品2 20公斤,价值100元
单位价值5元
物品2 物品1 物品2
=¥100+120
物品3 30公斤,价值120元
solution = union(solution,x); // 添至解空间
} return solution;
} (1)候选集合 A:问题的最终解均取自于候选集合A。 (2)解集合S:解集合S不断扩展,直到构成满足问题的完整解。 (3)解决函数solution:检查解集合S是否构成问题的完整解。 (4)选择函数select:贪心策略,这是贪心算法的关键。 8 (5)可行函数feasible:解集合扩展后是否满足约束条件。
贪心算法的设计思路
贪心算法的设计思路是:总是做出
在当前看来最好的选择,即贪心算
法并不是从整体最优考虑,它所做
的选择只是在某种意义上的局部最 优选择。
6
贪心算法的求解过程
使用贪心算法求解问题应该考虑如下几个方面:
(1)候选集合A:为了构造问题的解决方案,有一个候选集合 A作为问题的可能解,即问题的最终解均取自于候选集合A。 (2)解集合S:随着贪心选择的进行,解集合S不断扩展,直 到构成满足问题的完整解。 (3)解决函数solution:检查解集合S是否构成问题的完整解 。 (4)选择函数select:即贪心策略,这是贪心法的关键,它指 出哪个候选对象最有希望构成问题的解,选择函数通常和目标 函数有关。 (5)可行函数feasible:检查解集合中加入一个候选对象是否 可行,即解集合扩展后是否满足约束条件。
相关文档
最新文档