第9章_蛮力_贪婪法_数据结构与算法.pptx
数据结构与算法 贪婪法PPT课件

4
5
6
453
2
2
6
把5子树的根与6子树的根用一条有向边相连成为一棵树,即完成两个 集合的合并,理解为原无向边 {1,3} 加入5子树。
西华大学数学与计算机学院 黄襄念
Union 操作规则: 考虑Find操作,如果树高越大,则Find操作的键比较次数就会增加。 上例Union操作没考虑这点,明显的缺点是Union后树高可能会变得 很大(想想:为什么?),最坏情况下树变成线性表(链表),Find 操作成为线性效率Ω(n)而非对数级。例如:集合{1}, {2}, {3}, {4}, {5} 的一种合并过程如图,最后得到一条线性链。需避免此种情况出现。
西华大学数学与计算机学院 黄襄念
3. 算法停止:全部顶点都包含于树中。 每次只扩展一个顶点,扩展次数 = |V|-1 = n-1
PrimMST (G) // 输入图 G = <V, E>,生成树 T = <VT, ET>
VT {v0 }
// 任选顶点v0 作为初始生成树
贪婪技术

第九章 贪婪技术
9.3 Dijkstra算法 算法
Dijkstra(G) 算法 //单起点最短路径的 单起点最短路径的Dijkstra算法 单起点最短路径的 算法 //输入:具有非负权重加权连通图 输入: 以及它的顶点s 输入 具有非负权重加权连通图G=<V,E>以及它的顶点 以及它的顶点 /*输出:对于 中的每个顶点 来说,从s到v的最短路径长度 v 以及路径 输出: 中的每个顶点v来说 的最短路径长度d 输出 对于V中的每个顶点 来说, 到 的最短路径长度 上倒数第二个顶点p 上倒数第二个顶点 v*/ Initialize(Q) for V中的每一个顶点 do 中的每一个顶点v 中的每一个顶点 dv= ∞; pv = null; Insert(Q,v, dv); ds = 0; Decrease(Q,s,ds); VT = Φ for i=0 to |V|-1 do u* = DeleteMin(Q) VT = VT ∪ {u*} 中每一个和u*相邻的顶点 相邻的顶点u for V-VT中每一个和 相邻的顶点 do if du*+w(u*,u)<du du=du*+w(u*,u); pu = u*; Decrease(Q,u,du);
Байду номын сангаас
剩下的障碍只有两个 现在剩下的障碍只有两个: 现在剩下的障碍只有两个: (1)对于每一个不在当前树当中的顶点,如何才能知道谁与 )对于每一个不在当前树当中的顶点, 顶点之间的边是最短的? 顶点之间的边是最短的? (2)用这样的算法生成的那棵树,是不是最小生成树? )用这样的算法生成的那棵树,是不是最小生成树?
第九章 贪婪技术
9.1 Prim算法 算法
Prim算法的思想: 算法的思想: 算法的思想 (1)从图的顶点中任意选定一个顶点,作为初始子树; )从图的顶点中任意选定一个顶点,作为初始子树; (2)贪婪地迭代,即简单地把不在树中的,离当前顶点最近 )贪婪地迭代,即简单地把不在树中的, 的一个点添加到树中(这里所谓的“最近” 的一个点添加到树中(这里所谓的“最近”:是指这个点和顶点相 连的边权重最小); 连的边权重最小); (3)如果所有的顶点都包含在树中,那么算法结束;否则, )如果所有的顶点都包含在树中,那么算法结束;否则, 返回第2步继续迭代 步继续迭代; 返回第 步继续迭代;
贪婪算法

第 1 章 贪婪算法虽然设计一个好的求解算法更像是一门艺术,而不像是技术,但仍然存在一些行之有效的能够用于解决许多问题的算法设计方法,你可以使用这些方法来设计算法,并观察这些算法是如何工作的。
一般情况下,为了获得较好的性能,必须对算法进行细致的调整。
但是在某些情况下,算法经过调整之后性能仍无法达到要求,这时就必须寻求另外的方法来求解该问题。
本章首先引入最优化的概念,然后介绍一种直观的问题求解方法:贪婪算法。
最后,应用该算法给出货箱装船问题、背包问题、拓扑排序问题、二分覆盖问题、最短路径问题、最小代价生成树等问题的求解方案。
1.1 最优化问题本章及后续章节中的许多例子都是最优化问题( optimization problem),每个最优化问题都包含一组限制条件( c o n s t r a i n t)和一个优化函数( optimization function),符合限制条件的问题求解方案称为可行解( feasible solution),使优化函数取得最佳值的可行解称为最优解(optimal solution)。
例1-1 [ 渴婴问题] 有一个非常渴的、聪明的小婴儿,她可能得到的东西包括一杯水、一桶牛奶、多罐不同种类的果汁、许多不同的装在瓶子或罐子中的苏打水,即婴儿可得到n 种不同的饮料。
根据以前关于这n 种饮料的不同体验,此婴儿知道这其中某些饮料更合自己的胃口,因此,婴儿采取如下方法为每一种饮料赋予一个满意度值:饮用1盎司第i 种饮料,对它作出相对评价,将一个数值si 作为满意度赋予第i 种饮料。
通常,这个婴儿都会尽量饮用具有最大满意度值的饮料来最大限度地满足她解渴的需要,但是不幸的是:具有最大满意度值的饮料有时并没有足够的量来满足此婴儿解渴的需要。
设ai是第i 种饮料的总量(以盎司为单位),而此婴儿需要t 盎司的饮料来解渴,那么,需要饮用n种不同的饮料各多少量才能满足婴儿解渴的需求呢?设各种饮料的满意度已知。
ACM蛮力(穷举)PPT课件

chicken=%-2d\n", j, x, y, z); j++;} } }
.
10
运行结果: Possible solutions to buy 100 fowls whith 100 wen:
1: cock=0 hen=25 chicken=75 2: cock=4 hen=18 chicken=78 3: cock=8 hen=11 chicken=81 4: cock=12 hen=4 chicken=84
.
14
#include "stdio.h" main() { int m, count=0;
运行结果: 52 157 262 367 472 577 682 787 892 997
for ( m=1; m<=1000; m++ )
if ( m%3==1&&m%5==2&&m%7==3)
{ printf("%5d",m);
count++;
if(count%5==0) printf("\n");
}
}
.
15
常用的蛮力法
1.搜索所有的解空间。 2.搜索所有的路径。 3.直接进行计算。
.
16
搜索所有的解空间
案例1:假金币 案例2:现在的时间是多少?
.
17
案例1:假金币
False coin
Time Limit:3000MS Memory Limit:10000K
蛮力法是一种直接解决问题的方法,常常 直接基于问题的描述和所涉及的概念定义。
蛮力算法

17
main1( ) { int *a,i,j,n; input(n); a=calloc(n+1,sizeof(int)); //申请存储空间 for (i=1; i<=n;i++) a[i]=1; for (i=1; i<=n;i++) for (j=i; j<=n;j=j+i) a[i]=1-a[i]; for (i=1; i<=n;i++) if (a[i]=0) print(i,”is free.”); } 算法分析1:以一次开关锁计算,算法的时间复杂度为 n(1+1/2+1/3+……+1/n)=O(nlogn)。
3
【例3.1】百钱百鸡问题。中国古代数学家张丘建在《算经》 中提出了著名的“百钱百鸡问题”:鸡翁一,值钱五;鸡母一, 值钱三;鸡雏三,值钱一;百钱买百鸡,翁、母、雏各几何? 算法设计1: 通过对问题的理解,可能会想到列出两个三元一次方程, 去解这个不定解方程,就能找出问题的解。这确实是一种办法, 但这里我们要用“懒惰”的枚举策略进行算法设计: 设x,y,z分别为公鸡、母鸡、小鸡的数量。 尝试范围:由题意给定共100钱要买百鸡,若全买公鸡最多 买100/5=20只,显然x的取值范围1~20之间;同理,y的取值范 围在1~33之间,z的取值范围在1~100之间。 约束条件: x+y+z=100 且 5*x+3*y+z/3=100
贪婪算法

中国数学建模-编程交流-贪婪算法feifei7 重登录隐身用户控制面板搜索风格论坛状态论坛展区社区服务社区休闲网站首页退出>> VC++,C,Perl,Asp...编程学习,算法介绍. 我的收件箱(0)中国数学建模→学术区→编程交流→贪婪算法您是本帖的第672 个阅读者* 贴子主题:贪婪算法b等级:职业侠客文章:472积分:951门派:黑客帝国注册:2003-8-28第11 楼1.3.6 最小耗费生成树在例1 - 2及1 - 3中已考察过这个问题。
因为具有n个顶点的无向网络G的每个生成树刚好具有n-1条边,所以问题是用某种方法选择n-1条边使它们形成G的最小生成树。
至少可以采用三种不同的贪婪策略来选择这n-1条边。
这三种求解最小生成树的贪婪算法策略是:K r u s k a l算法,P r i m算法和S o l l i n算法。
1. Kruskal算法(1) 算法思想K r u s k a l算法每次选择n-1条边,所使用的贪婪准则是:从剩下的边中选择一条不会产生环路的具有最小耗费的边加入已选择的边的集合中。
注意到所选取的边若产生环路则不可能形成一棵生成树。
Kr u s k a l算法分e 步,其中e 是网络中边的数目。
按耗费递增的顺序来考虑这e条边,每次考虑一条边。
当考虑某条边时,若将其加入到已选边的集合中会出现环路,则将其抛弃,否则,将它选入。
考察图1-12a 中的网络。
初始时没有任何边被选择。
图13-12b 显示了各节点的当前状态。
边(1 ,6)是最先选入的边,它被加入到欲构建的生成树中,得到图1 3 - 1 2 c。
下一步选择边(3,4)并将其加入树中(如图1 3 -1 2 d所示)。
然后考虑边( 2,7 ),将它加入树中并不会产生环路,于是便得到图1 3 - 1 2 e。
下一步考虑边(2,3)并将其加入树中(如图1 3 - 1 2f所示)。
在其余还未考虑的边中,(7,4)具有最小耗费,因此先考虑它,将它加入正在创建的树中会产生环路,所以将其丢弃。
算法-第9章-贪婪技术(李静)

Prim算法
❖ Prim算法要求:对于每个不在当前树 中的顶点,必须知道它连接树中顶点 的最短边的信息
每一个顶点附加两个标记:
❖树中最近顶点的名称 ❖相应边的权重
Prim算法
b 1c
34
4
6
a 5f 5 d
62
8
e
算法 Prim(G){//构造最小生成树
S={v , v ,v ,v }
引入辅助数组dist。它的每一个分量dist[i]表 示当前找到的从源点 v0到终点 vi 的最短路径 的长度。初始状态:
若从源点v0到顶点 vi 有边, 则dist[i]为该边 上的权值;
若从源点v0到顶点 vi 无边, 则dist[i]为 。
假设 S 是已求得的最短路径的终点的集合,则 可证明:下一条最短路径必然是从v0 出发,中 间只经过 S 中的顶点便可到达的那些顶点vx (vxV-S )的路径中的一条。
}
return ET; }
Prim算法是否能产生一个最优解
用归纳法和反证法来证明: 假设Ti-1是某些最小生成树T的一部分,我们需要证明,通过 Prim算法从Ti-1成生的Ti也是一棵最小生成树的一部分。
Prim算法的效率
❖ Prim算法的效率取决于
表示图本身的数据结构
表示集合V-VT的优先队列的数据结构
❖ 问题描述
已知有n种物品和一个可容纳W重量的背包,每种物品I的 重量为wi,假定将物品I的某一部分xi放入背包就会得到pixi 的效益(0≤xi≤1, pi>0) ,采用怎样的装包方法才会使装 入背包物品的总效益为最大呢?
❖ 问题的形式描述
蛮力法

2 查找问题中的蛮力法—串的匹配
BF算法
KMP算法
下一次开始位置 下一次开始位置
本趟开始位置
i 回溯
ii
S 模式T
si
…
tj
回溯
j
j
回溯next[j]
……
3 排序问题中的蛮力法—选择排序
选择排序开始的时候,扫描整个序列,找到整个序列的最小记
录和序列中的第一个记录交换,从而将最小记录放到它在有序
区的最终位置上,然后再从第二个记录开始扫描序列,找到n-1
个序列中的最小记录,再和第二个记录交换位置。一般地,第i
趟排序从第i个记录开始扫描序列,在n-i+1(1≤i≤n-1)个记录中
找到关键码最小的记录,并和第i个记录交换作为有序序列的第i
个记录。
4 组合问题中的蛮力法—任务分配问题
可以用一个n元组(j1, j2, …, jn)来描述任务分配问题的一个可能 解,其中第i个分量ji(1≤i≤n)表示在第i行中选择的列号,因此 用蛮力法解决任务分配问题要求生成整数1~n的全排列,然后把 成本矩阵中的相应元素相加来求得每种分配方案的总成本,最 后选出具有最小和 18
是否最短
否 是 否 是 否 否
蛮力法求解TSP问题存在的问题
注意到图中有3对不同的路径,对每对路径来说,不同 的只是路径的方向,因此,可以将这个数量减半,则 可能的解有(n-1)!/2个。随着n的增长,TSP问题的可 能解也在迅速地增长。
一个10城市的TSP问题有大约180,000个可能解。 一个20城市的TSP问题有大约
依次处理所有元素是蛮力法的关键,为 了避免陷入重复试探,应保证处理过的 元素不再被处理。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
5/28
蛮力法应用 —— 一种重要的算法设计方法
解决各种问题的一般方法 常用于一些很基本又重要的算法 —— 计算 n 个数的和 —— 求数据集的最大元素,…… 可作为尺度,衡量同样问题的其他算法的效率 对于规模不大的问题(蛮力法的速度可以接受时) 蛮力法是一种很好的解决方案! 设计高效算法的代价很可能是不值得的: ① 算法可读性变差,算法实现的复杂性增加 软件工程:不利于软件的开发、测试、维护 ② 时间效率得不到显著的体现
6
20:42
16/28
算法过程图例
树中顶点集 初始树 A(, ) 候选顶点集
B ( A, 3), C ( , ) D( , ), E ( A, 6) F ( A, 5)
B
3
4
1
C
4
6 5
A
5 6
F
2
D
8
E B
1
C
4
A(, ), B( A, 3)
C ( B,1), D( , ) E ( A, 6), F ( B, 4)
穷举查找:最近对问题、凸包问题
20:42
7/28
排序算法设计
举例:对线性表 (89, 45, 68, 90, 29, 34, 17) 排为升序 思考:什么是排序问题?最直接的排序方法? 蛮力法:按从小到大顺序挑出各个元素排列好 2 3 4 5 6 n 7 SelectionSort ( A[1...n]) { 45 68 90 29 34 17 for i 1 to n 1 45 68 95 34 89 for j i 1 to n 29 34 90 45 68 89 if ( A[ j ] A[min] ) min j 29 34 45 90 68 89 A[ i ] A[min] 29 34 45 68 90 89 } 29 34 45 68 89 90
蛮力法:直接基于问题本身描述的算法设计方法 解决问题没有或不用技巧(简单、直接) 简例 已知 a 和非负整数 n,计算 an 的蛮力算法:
a a aa ... a
n n个
典型算法:各种穷举法
优缺点
优点:算法设计简单,易于设计 缺点:算法的时间效率一般不高
20:42
19/28
B 树中边集 ET 有序候选边集 E BC, EF, AB, BF, CF 1 2 3 4 4 AF, DF, AE, CD, DE 5 5 6 6 8
3
4
1
C
4
6 5
A
5 6
F
2
D
Φ
8
E B
3
4
1
C
4
6 5 8
BC
BC, EF, AB, BF, CF 1 2 3 4 4 AF, DF, AE, CD, DE 5 5 6 6 8
Kruskal 算法 (克鲁斯卡尔, 避环法)
策略:初始森林开始,逐步合并森林,直到生成 MST 1 Kruskal 算法 // 网G=<V,E,W> B C 4 4 3 6 { O(eloge), e 边数 A 5 F 5 D G 的边集 E 排序:权值小→大 2 初始森林:MST 的边集 ET = Φ 6 8 E while( |ET| <= n-1 ) // MST有多少边? { 从 E 取下一条边 {u, v} ; E = E - {u, v} ; if ({u,v} 与 ET中边不构成回路 ) ET = ET∪{u,v} ; // {u, v} 加入MST } } 判断 u, v 是否属于同一棵树 (极小连通子图)
一个承重量为 W 的背包 求解:能够放入背包(可行)、最有价值的子集 (最优) 连续背包 物品可以按任意比例切分,比例系数 (0.0~1.0) 离散背包(0-1背包) 物品不能切分。0:不放入, 1:放入
0-1背包的蛮力法 (穷举查找)
① 生成 n 个物品集合的全部子集(所有组合) ② 计算每个子集的重量(≤W) ,计算可行解的价值 ③ 最优解:可行解中价值最大者
20:42
12/28
生成树 (Spanning Tree, ST)
包含连通图全部顶点的一个连通无环子图 (边数 = n-1) 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
最小生成树 (Minimum Spanning Tree, MST)
带权连通图所有生成树中,权重之和最小的那一棵 A 1 B A 1 B A 1 B A 1 B 2 2 2 5 5 5 C 3 D C 3 D w(T1) = 6 3 D w(T2) = 9 C C D w(T3) = 8
20:42
13/28
普利姆 (Prim) 算法
策略:初始子树开始,逐步扩展子树,直到生成 MST 算法: ① 初始子树 任选一个顶点 v0 ② 子树扩展(贪婪) 加入顶点:不在树中、到树的距离最近的一个顶点 ○ 顶点到树的距离:到树中所有顶点的最短距离 ③ 算法停止 全部顶点都已加入树中(形成一棵树) 说明:MST不唯一,但权之重和相同 算法过程图:下页
20:42
11/28
每一步的决策
是可行解(满足约束条件) 局部最优(贪婪) 不可逆转(后续步骤不能改变它)
优缺点
优点:算法较简单,时空效率较高 缺点:存在视界局限(局部最优不一定是全局最优), 对某些优化问题,不能获得最优解!
负梯度只是局部最好方向, 相邻两次迭代的方向垂直, 整个搜索轨迹呈现锯齿形! 若函数性态很坏,震荡现象 严重,甚至计算不收敛。
BC, EF, AB, BF, CF 1 2 3 4 4 AF, DF, AE, CD, DE 5 5 6 6 8
A
5 6
F
2
D
E
B
3
4
1
C
4
BC,EF
6 5
A
5 6
F
2
D
8
E
20:42
20/28
B 树中边集 ET 有序候选边集 E BC, EF, AB, BF, CF 不 1 2 3 4 4 唯 AF, DF, AE, CD, DE 一 5 5 6 6 8
Data Structures and Algorithms
主讲教师 : 黄襄念 西华大学数学与计算机学院
图像处理与模式识别实验室
课程QQ群:101600501
2/28
20:42
3/28
数学描述
算法设计
数据结构设计 程序设计
20:42
4/28
蛮力法(Brute Force Algorithm)
穷举查找
① 设计生成算法,生成全部子集(个数:2n ) 幂集
② 对所有子集一一判定是否满足约束条件:
满足的子集:解(可行解) 不满足的子集:不可行解
20:42
9/28
背包问题(Knapsack Problem) 已知:n 个物品,重量 (w1, ..., wn), 价值 (v1, ..., vn),
1 89 17 17 17 17 17 17
n( n 1) 2 T ( n) 1 ( n ) 2 i 1 j i 1
n1 n
20:42
8/28
组合问题的查找
前述查找:给定集合中查找满足条件的一个元素 (key) 组合问题的查找:给定集合中查找满足条件的子集 例:子集和问题 在给定的整数集合中,查找满足如下条件的子集: 元素和 = 某个给定的整数 (约束条件) 应用例:食堂就餐(50元钱能买多少食品,不找零)
3
4
6 5
A
5 6
F
2
D
8
E
20:42
17/28
B
3
4
1
C
4
6 5
树中顶点集
A( , ), B( A, 3) C ( B ,1) A( , ), B( A, 3) C ( B ,1), F ( B , 4)
候选顶点集
A
5 6
F
2
D
D(C , 6), E ( A, 6) F ( B , 4) MST 不唯一
xk (0,1) , k 1, ..., n
0 xk 1
三种贪婪策略 ① 价值贪婪 ② 重量贪婪 ③ 价值/重量贪婪
20:42
24/28
GreedyKnapsack ( n, w[1...n], v[1...n], x[1...n],W ,V ) x[1...n] 0 // 解向量 (空背包) W0 W // 背包的当前承重量 V 0 // 背包中物品总价值 MergeSort (v[1...n] / w[1...n]) // 排序(降序):价值/重量 for ( i 1 to n) do // n个物品循环 if ( w[i ] W0 ) then // 未超重 x[i ] 1 // 整个装入背包:xi = 1 // 背包当前承重量减小 W0 W0 w[i ] // 物品价值记入总价值 V V v[i ] // 物品超重:放入一部分 else x[i ] W0 / w[i ], V V x[ i ] * v[i ] break return V
20:42
23/28
背包问题的数学模型(优化模型)
目标函数
max f ( x ) vk xk
k 1
n
约束条件 0-1 背包 连续背包
w x
k 1 k
n
k
W
n 个物品: 重量: (w1, ..., wn) 价值 : (v1, ..., vn)
背包承重量 : W 物品 k 放入背包的 比例系数: xk
20:42
6 5