算法设计 分支限界法倒推法
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
v2
v3 v4 v5
9 50 24 ∞ 6
10 ∞
2013-7-4
11 of 158
答案 1 →2 →3 →5→4→1:62
21
47
~21
45
53 14 64
50
~45
68 ~14 23 62 35 ~35 62
41
62
~41 74
~23 70
65
62
2013-7-4
66
12 of 158
方法概述: 基本思想
先进先出队列(F I F O) : 即从活结点表中 取出结点的顺序与加入结点的顺序相同,因 此活结点表的性质与队列相同; 优先队列(耗费用小根堆,受益用大根堆): 每个结点都有一个对应的耗费或收益。 -如果查找一个具有最小耗费的解,则活结点 表可用最小堆来建立,下一个扩展结点就是 具有最小耗费的活结点; -如果希望搜索一个具有最大收益的解,则可 用最大堆来构造活结点表,下一个扩展结点 是具有最大收益的活结点。
v1
v1 v2 ∞ 9 7 ∞ 0 2 13 8 10 0 ∞ 8 7 ∞
v3 v4 v5 24 ∞ 1 7 ∞ 0 23 7 1 1 8 0 2 0 ∞
1
h~14=20 h~25=19 h~31=26 h~45=26 h~52=20 h~53=25
2013-7-4
v2 v3 v4 v5
10 ∞
18
为了有效地选择下一扩展结点,以加 速搜索的进程,在每一活结点处,计 算一个函数值(限界),并根据这些 已计算出的函数值,从当前活结点表 中选择一个最有利的结点作为扩展结 点,使搜索朝着解空间树上有最优解 的分支推进,以便尽快地找出一个最 优解。
14 of 158
2013-7-4
方法概述: 与回溯法的区别
18
~31 26
~45 26
53不能选 选择23,52
v2
v5 0
31,45,14,23,52 1→4 → 5 → 2 → 3 → 1 总花费是:25
2013-7-4
10 of 158
课堂练习
v1 v1 v2 v3 v4 v5 ∞ 25 40 31 27 5 ∞ 19 15 22 8 17 ∞ 7 30 25 6 1
子集和问题
问题
给定由n个不同正数组成的集合 W={wi},和正数M,求W中所有 和等于M的子集的集合; 例如n = 6, M = 30, W={10, 13, 5, 18, 12, 15}
2013-7-4
1 of 158
子集和问题
按照回溯法思想,从状态树的根结点出 发,做深度优先搜索; 为便于计算,将W中的正数按从小到大 排序; 当在某一状态A下,依次尝试加入和不加 入正数wi,若∑A+wi>M,则可停止对该 结点的搜索;若∑A+ ∑(wi…wn)<M,则 也可停止对该结点的搜索;
2013-7-4
19 of 158
堆
堆
A[1] A[2] A[4] A[8] A[9]
20 of 158
A[3] A[6] A[7]
A[5]
2013-7-4
堆
堆
所构造的树有如下性质
所有叶子在树的最底层或倒数第二层 如果最底层的节点不能完全填满,则总是在最左 边
这样的树叫左-完全二叉树
v2 ∞
v4 8 v5 0
10 ∞ 0 18
10 ∞
v5
31 18
18
~31 26
2013-7-4
8 of 158
h~14=20 h~25=19 h~45=26 h~52=26 h~53=25
v1
v1
v2 9
v3 ∞ 7 0
v4 v5 0 1 1 8 31 0 0 ∞ 18 18 ~31
v1
v2 9
求解目标不同 :
一般而言,回溯法的求解目标是找出解空间树 中满足约束条件的所有解,而分支限界法的求解 目标则是找出满足约束条件的一个解;
搜索方法不同:
回溯算法使用深度优先方法搜索,而分枝限界 一般用宽度优先或最小耗费方法来搜索;
2013-7-4
15 of 158
方法概述: 与回溯法的区别
对扩展结点的扩展方式不同:
分支限界法中,每一个活结点只有一次机会成 为扩展结点。活结点一旦成为扩展结点,就一次 性产生其所有儿子结点;
存储空间的要求不同:
相对而言,分枝限界法的存储空间比回溯法大 得多,因此当内存容量有限时,回溯法成功的可 能性更大;
2013-7-4
16 of 158
方法概述: 求解步骤
①定义解空间(对解编码); ②确定解空间的树结构; ③按BFS等方式搜索:
1
∞ 0 0 0 0 ∞
31 ?
18
~31 26
0 2
13 8 10 0
∞ 0 2
10 ∞ 0 7
20 (=18+1+1)
7 of 158
走31的计算方法
v1 v2 v3 v4 v1 v2 ∞ 9 7 ∞ 0 2 13 8 10 0 v3 v4 v5 24 0 1 7 ∞ 0 1 1 8 0 2 0 ∞ 18 v1 v2 9 v3 ∞ 7 0 v4 v5 0 1 1 8 0 ∞
∞ 14 30 10 ∞ 5 5 6 3 6 2 11 4 ∞
D=
4
6
15 10 13 ∞ 13 3
2013-7-4
4 11 ∞
5 of 158
规定:先做行规约,再做列规约
∞ 14 30 5
10 ∞ 11 ∞ 4 5
6
3 6
5
∞ 9 0 2 13 8 10 0
25
0 1 8 18
1 2 0 ∞
3 先行规约 7 ∞
堆
堆—堆调整
假设已经有一个现成的(大顶)堆,调整的 目的是把堆顶(根)的最大元素和序列的最 后一个元素交换,然后把剩下是元素继续建 成堆
2013-7-4
24 of 158
堆
堆—堆调整
50 24
6 24
30
30
20
21
18
3
20
21
18
3
12
5
6
12
5
50
假设已经有一个堆,把堆顶 元素和最后一个元素交换
v3 v4 v5 ∞ ∞ 1 7 0 1 8 0 0 ∞ 18 10 ∞
v2 ∞
v4 8 v5 0
v2 ∞ v4 8 v5 0
10 ∞
v2 9
v3 ∞
7 0
v4 0
1 ∞
v2 ∞
45 ?
18
~45 26
26
v5 0
2013-7-4
18
9 of 158
31 45 19 14 25 v2 v3 ∞ 0 0 25 ~14 28 18
2 of 158
2013-7-4
分支限界法
例: 非对称的货郎担问题 规律: 1)根结点是所有路线的下界 2)从目前所有叶子中下界最小的作为 分支点,按某种分支法产生若干个子 集,再分别求各自的下界。
31 18
2013-7-4
18
~31 60
4 of 158
首先考虑根结点,即求所有路线的下界。对D 的每行减去该行的最小元素或每列减去该列的 最小元素,得到一个新的矩阵,使得每行和每 列至少有一个零元素。这叫做行规约和列规约。
4 2
8
∞ 1 1
1 0
D=
4
6
15 10 13 ∞
13 3
2
11 ∞
4 11 ∞ 3 ∞ 9 24 0 7 ∞ 0 2 13 8 10 0 7 ∞ 0 1 1 8
1
0 2 0 ∞
再列规约
首先计算第一个0 所对应的边14
2013-7-4
记作
10 ∞
D’
18 (=5+3+4+2+3+1)
6 of 158
1 0
1
B
0
1 0 1
C
0
D H
2013-7-4
1
I
0
1
E K L
F
J
M
0 1
G
N
0
O
32 of 158
方法概述: 示例1
③BFS搜索(FIFO队列)
扩展结点 A B C E F G 活结点 队列(可行结点) B,C BC D,E(D死结点) CE F,G EFG J,K(J死结点) FG L,M G N,O φ
示例2(优先队列分枝限界法) 问题: 0-1背包问题:物品数n=3, 重量 w=(20,15,15), 价值v=(40,25,25), 背包容量 c=30, 试装入最大价值之和的物品? 求解: ①解空间:{(0,0,0), (0,0,1), … , (1,1,1)} ②解空间树: 1 A 0
在解空间树中, 以广度优先BFS或最 佳优先方式搜索最优解, 利用部分解 的最优信息, 裁剪那些不能得到最优 解的子树以提高搜索效率。 搜索策略是:在扩展结点处,先生成 其所有的儿子结点(分支),然后再 从当前的活结点表中选择下一个扩展 结点。
13 of 158
2013-7-4
方法概述: 基本思想
堆
堆—堆建立
堆建立是把一个无序的序列建成一个堆的过程
它是思想是从最底层的子树进行堆调整,先将子树建成堆,
然后继续调整,直到整个树构成堆
20 50 50
30
24
30
21
24
18
3
21
20
18
3
12
2013-7-4
5
6
12
5
6
30 of 158
堆
堆—堆建立
最后一个非叶节点是从[n/2]开始的,所以从这个节点开始
1
B
0
1 0 1
C
0
D H
2013-7-4
1
I
0
1
E
F
J
K
L
M
0 1
G N
0
O
34 of 158
方法概述: 示例2
BFS搜索(优先队列:按价值率优先) 扩展结点 活结点 堆(可行结点) B A B,C C B D,E(D死结点)
1 1 1
可行解(叶结点)
解值
K L,M N,O
40 50,25 25,0
A
0 1
w=(20,15,15),
0
B
0
C
v=(40,25,25), c=30
0
D
H
2013-7-4
I J
0 1
E
K
0
L M N O
33 of 158
1
F
0 1
G
∴ 最优解为L, 即(0,1,1); 解值为50
方法概述: 示例2
18 of 158
2013-7-4
堆(Heap)
堆
给定一个序列A[]={A[1], A[2], …, A[n]}, 可 以按如下的方式构造一棵二叉树:
A[1]为根 对任何一个A[i], 它的左儿子是A[2i], 右儿子是 A[2i+1] 如果2i或2i+1超过n,则A[i]没有相对应的那个儿 子
2013-7-4
50
24
12
50
6
28 of 158
堆
堆—堆建立
堆建立是把一个无序的序列建成一个堆的过程
它是思想是从最底层的子树进行堆调整,先将子树建成堆,
然后继续调整,直到整个树构成堆
20 21 21 20
3
30
50
24
18
30
50
24
18
3
12
2013-7-4
5
6
12
5
6
29 of 158
a.每个活结点仅有一次机会变成扩展结点; b.由扩展结点生成一步可达的新结点; c.在新结点中, 删除不可能导出最优解的结点; //剪枝 策略 d.将余下的新结点加入活动表(队列)中; e.从活动表中选择结点再扩展; //选择策略 f.直至活动表为空;
2013-7-4
17 of 158
方法概述: 两种常见的活结点扩充方式
堆
堆—堆调整
30 24
18
20
21
6
3
12
5
50
3) 新堆构成
2013-7-4 27 of 158
堆
堆—堆建立
堆建立是把一个无序的序列建成一个堆的过程
它是思想是从最底层的子树进行堆调整,先将子树建成堆,
然后继续调整,直到整个树构成堆
20 21
21 20 3
3
5
6
18
30
5
24
18
30
12
或
A[i] A[2i ] A[i] A[2i 1]
小顶堆
22 of 158
堆
堆
12,36, 24, 85, 47, 30,53,91
12
96,83, 27, 38, 11, 9
96
36 83 27 24
85
38 11 9 91
47
30
53
2013-7-4
23 of 158
向前调整
void HeapConstruction(T Array[], int len){
for(int i = len/2; i > 0; i--){
HeapAdjust(Array, i, len); }
}
2013-7-4
31 of 158
方法概述: 示例1
示例1(FIFO队列分枝限界法) 问题: 0-1背包问题:物品数n=3, 重量 w=(20,15,15), 价值v=(40,25,25), 背包容量 c=30, 试装入最大价值之和的物品? 求解: ①解空间:{(0,0,0), (0,0,1), … , (1,1,1)} ②解空间树: A
2013-7-4
0) 剩下的序列中,堆的性质被破 坏,调整堆就是把剩余的序列重 新建成堆 25 of 158
堆
堆—堆调整
6 24 24 30 30
6
20
21
18
3
20
21Fra Baidu bibliotek
18
3
12
5
50
12
5
50
1) 新的堆顶元素小于它的儿子, 2) 调整后,右子树的根仍小于它 所以不能构成堆,调整它的 的儿子,所以把它和它的大儿 2013-7-4 26 of 158 位置把它和较大的儿子交换 子交换
2013-7-4
21 of 158
堆
堆
如果一个左-完全二叉树有下列性质:
任何一个非叶节点的值都大于等于(或小于等于) 它的儿子的值
则这个树称为大(小)顶堆 一个堆对应的序列显然有如下性质:
A[i ] A[2i ] A[i ] A[2i 1]
大顶堆
2013-7-4