45
复复复复复复复复复 复复复复复复复复复 16.1 16.1 复复复复复复复 复复复复复复复 16.2 16.2 复复复复复复复 复复复复复复复 复复复复 复复复复 复复复复复复复复复复TSP TSP 复复复复Chapter16 Chapter16 回回 回回 22/6/9 1

Chapter16 回溯

  • Upload
    ocean

  • View
    91

  • Download
    0

Embed Size (px)

DESCRIPTION

Chapter16 回溯. 复杂问题解法的提示 16.1 回溯算法的思想 16.2 回溯算法的应用 货箱装船 旅行商问题( TSP 问题). 1 、寻求问题解的常规思路. 首先列出所有候选解 然后依次检查每一个解,直到找到所需的解 【 可行性前提 】 :候选解数量有限,并且能够通过检查所有或部分候选解得到所需的解. 示例 1 :百元百鸡问题. 使用枚举法求解:百元买百鸡问题 公鸡每只 5 元,母鸡每只 3 元,小鸡 3 只 1 元 x+y+z=100 5x+3y+z/3=100 1

Citation preview

Page 1: Chapter16  回溯

复杂问题解法的提示复杂问题解法的提示16.1 16.1 回溯算法的思想 回溯算法的思想 16.2 16.2 回溯算法的应用回溯算法的应用

货箱装船货箱装船旅行商问题(旅行商问题( TSPTSP 问题)问题)

Chapter16 Chapter16 回溯回溯

23/4/21 1

Page 2: Chapter16  回溯

11 、寻求问题解的常规思路 、寻求问题解的常规思路 首先列出所有候选解首先列出所有候选解 然后依次检查每一个解,直到找到所需的解然后依次检查每一个解,直到找到所需的解 【【可行性前提可行性前提】】:候选解数量有限,并且能够通过检查:候选解数量有限,并且能够通过检查

所有或部分候选解得到所需的解所有或部分候选解得到所需的解

23/4/21 2

Page 3: Chapter16  回溯

示例示例 11 :百元百鸡问题:百元百鸡问题• 使用枚举法求解:百元买百鸡问题使用枚举法求解:百元买百鸡问题• 公鸡每只公鸡每只 55 元,母鸡每只元,母鸡每只 33 元,小鸡元,小鸡 33 只只 11 元元• x+y+z=100x+y+z=100

• 5x+3y+z/3=1005x+3y+z/3=100

• 1<=x<=201<=x<=20 ,, 1<=y<=331<=y<=33

• 解法:枚举所有满足条件的候选解解法:枚举所有满足条件的候选解• 缺点:运算量大;改进:找到限定规则缺点:运算量大;改进:找到限定规则

23/4/21 3

Page 4: Chapter16  回溯

对候选解进行系统检查的常用方法对候选解进行系统检查的常用方法

回溯回溯分支定界分支定界

• 避免对很大的候选解集合进行检查,同时能够保证算法避免对很大的候选解集合进行检查,同时能够保证算法运行结束可以找到所需要的解;运行结束可以找到所需要的解;

• 通常能够用来求解规模很大的问题。通常能够用来求解规模很大的问题。

23/4/21 4

Page 5: Chapter16  回溯

回溯算法思想回溯算法思想• 回溯算法,也叫试探算法。回溯算法,也叫试探算法。• 是一种系统的搜索问题的解的方法。是一种系统的搜索问题的解的方法。• 【【基本思想基本思想】】从一条路往前走,能进则进,不能进则退从一条路往前走,能进则进,不能进则退

回来,换一条路再试。回来,换一条路再试。

23/4/21 5

Page 6: Chapter16  回溯

示例示例 22 :: nn 皇后问题皇后问题• 在 在 n n 行 行 n n 列的国际象棋列的国际象棋

棋盘上,若两个皇后位于棋盘上,若两个皇后位于同一行、同一列、同一对同一行、同一列、同一对角线上,则称它们为互相角线上,则称它们为互相攻击。攻击。

• 【【 nn 皇后问题皇后问题】】找到这 找到这 n n 个皇后的互不攻击的布局。个皇后的互不攻击的布局。

8x8 Chessboard8x8 Chessboard

23/4/21 6

Page 7: Chapter16  回溯

查找时间与问题规模相关查找时间与问题规模相关

4x44x4

8x88x823/4/21 7

Page 8: Chapter16  回溯

用回溯算法解决问题的一般步骤用回溯算法解决问题的一般步骤• 一、定义一个解空间,这个解空间必须至少包含问题的一个解(可能一、定义一个解空间,这个解空间必须至少包含问题的一个解(可能最优);最优);• 二、用易于搜索的方式组织该解空间。典型的组织方式是图(如迷二、用易于搜索的方式组织该解空间。典型的组织方式是图(如迷宫)或树(如宫)或树(如 0/10/1 背包)。背包)。• 三、按深度优先法从开始节点进行搜索。 三、按深度优先法从开始节点进行搜索。 • 四、利用限界函数避免移动到不可能产生解的子空间。四、利用限界函数避免移动到不可能产生解的子空间。

【【回溯算法重要特性回溯算法重要特性】】问题的解空间通常是在搜索问题的解空间通常是在搜索问题的解的过程中动态产生的。问题的解的过程中动态产生的。

23/4/21 8

Page 9: Chapter16  回溯

示例:示例: 3*33*3 迷宫问题(图迷宫问题(图 16-116-1 ))• 11 、定义解空间:、定义解空间:

– 包含从入口到出口的所有路径;包含从入口到出口的所有路径;• 22 、组织解空间:、组织解空间:

– 用图的形式给出。用图的形式给出。– 从点从点 (1,1)(1,1) 到到 (3,3)(3,3) 的每一条路径都定义了的每一条路径都定义了 3*33*3 迷迷

宫解空间中的一个元素;宫解空间中的一个元素;• 33 、搜索解空间:、搜索解空间:

– 从开始节点(从开始节点( 11 ,, 11 )进行深度优先搜索。)进行深度优先搜索。

23/4/21 9

Page 10: Chapter16  回溯

示例:示例: nn 个对象的个对象的 0/10/1 背包问题(图背包问题(图 16-216-2 ))

• 11 、定义解空间:、定义解空间:– 22nn 个长度为个长度为 nn 的的 0/10/1 向量集合;向量集合;– n=3n=3 时,解空间时,解空间 {(0,0,0),(0,1,0),(0,0,1,(1,0,0),(0,1,1),{(0,0,0),(0,1,0),(0,0,1,(1,0,0),(0,1,1),

(1,0,1,(1,1,0),(1,1,1))}(1,0,1,(1,1,0),(1,1,1))}• 22 、组织解空间:、组织解空间:– 用树的形式给出。用树的形式给出。– 第第 ii 层到第层到第 i+1i+1 层节点的一条边上的数字:向量层节点的一条边上的数字:向量 xx 中第中第

ii 个分量的值个分量的值 xixi ;;– 从根节点到叶节点的每一条路径都定义了解空间中的从根节点到叶节点的每一条路径都定义了解空间中的

一个元素。一个元素。• 33 、搜索解空间:、搜索解空间:– 开始节点为根节点进行深度优先搜索。开始节点为根节点进行深度优先搜索。

23/4/21 10

Page 11: Chapter16  回溯

活节点、死节点和活节点、死节点和 E-E- 节点节点• 活节点:开始节点是活节点,也是活节点:开始节点是活节点,也是 E-E- 节点。节点。• 死节点死节点• E-E- 节点(节点( Expansion NodeExpansion Node )及回溯)及回溯– 从从 EE 节点可移动到一个新的节点;节点可移动到一个新的节点;– 如果能从当前节点移动到一个新的节点,则这个新节如果能从当前节点移动到一个新的节点,则这个新节

点将变成一个活节点和新的点将变成一个活节点和新的 E-E- 节点;旧的节点;旧的 E-E- 节点仍然节点仍然是个活节点。是个活节点。

– 如果不能够移到一个新节点,则该如果不能够移到一个新节点,则该 E-E- 节点成为死节点,节点成为死节点,只能返回到最近被考察的活节点(回溯),这个活节只能返回到最近被考察的活节点(回溯),这个活节点变成新的点变成新的 E-E- 节点。节点。

– 当已经找到答案或者回溯尽了所有的活节点时,搜索当已经找到答案或者回溯尽了所有的活节点时,搜索过程结束。过程结束。

23/4/21 11

Page 12: Chapter16  回溯

限界函数限界函数• 通过确定一个新近到达的节点能否导致一个比当前最优解还要好通过确定一个新近到达的节点能否导致一个比当前最优解还要好

的解,可以加速对最优解的搜索。的解,可以加速对最优解的搜索。• 如果不能,则移动到该节点的任何一个子树都是无意义的,这个如果不能,则移动到该节点的任何一个子树都是无意义的,这个

节点可被立即杀死。节点可被立即杀死。• 用来杀死活节点的策略称为:限界函数(用来杀死活节点的策略称为:限界函数( Bounding FunctionBounding Function )。)。

23/4/21 12

Page 13: Chapter16  回溯

解空间图:解空间图: 3*33*3 迷宫老鼠问题迷宫老鼠问题(( P185 P185 程序程序 5-135-13 回溯算法)回溯算法)

• 寻找从寻找从 (1(1 ,, 1)1) 到到 (3(3 ,, 3)3) 的一条路径的一条路径左图中,从起点到终点的每一条左图中,从起点到终点的每一条路径都定义了解空间中的一个元素。路径都定义了解空间中的一个元素。

搜索结果:搜索结果: (1,1)-(2,1)-(3,1)-(3,2)-(3,3)(1,1)-(2,1)-(3,1)-(3,2)-(3,3)23/4/21 13

Page 14: Chapter16  回溯

解空间树:解空间树: 0/10/1 背包问题背包问题

• 从从 nn 个物品中选择装入背包的物品个物品中选择装入背包的物品• 约束条件:约束条件:

n

iixip

ix

n

ic

ixiw

1]1,0[

1取得最大值,并且,

• 左图为左图为 n=3n=3时的解空间树时的解空间树

Page 15: Chapter16  回溯

n=3n=3 时,时, 0/10/1 背包问题的求解过背包问题的求解过程程

• w=[20,15,15], p=[40,25,25], c=30w=[20,15,15], p=[40,25,25], c=30 剩余容量剩余容量 收益收益

1010 4040

当前最优当前最优 : : ABEKABEK

1515 2525

00 5050

最优解最优解 : ACFL: ACFL

【【限界函数限界函数】】杀死代表不可行解决方案的节点。杀死代表不可行解决方案的节点。

Page 16: Chapter16  回溯

示例:旅行商问题(示例:旅行商问题( TSPTSP ))

• 旅行商需要找到一条从家里出发,访问所有城市后返回旅行商需要找到一条从家里出发,访问所有城市后返回原处的旅游环路。原处的旅游环路。

• 要求:路径最短或耗费最小要求:路径最短或耗费最小

Home cityHome city

Visit cityVisit city

23/4/21 16

Page 17: Chapter16  回溯

旅行商问题的定义旅行商问题的定义• 顶点:旅行商所要旅行的城市(包顶点:旅行商所要旅行的城市(包括起点)括起点)

• 边的耗费:给出了在两个城市旅行边的耗费:给出了在两个城市旅行所需的时间(或花费)所需的时间(或花费)

• 旅行:表示当旅行商游览了所有城旅行:表示当旅行商游览了所有城市再回到出发点时所走的路线市再回到出发点时所走的路线

例如:旅行例如:旅行 1-3-2-4-11-3-2-4-1的耗费为的耗费为 2525 ,最小!,最小!

23/4/21 17

Page 18: Chapter16  回溯

解空间描述:排列树解空间描述:排列树

• 一个旅行:由树中的一条从根到叶的路径表示。一个旅行:由树中的一条从根到叶的路径表示。• 例如:例如: ABCFLABCFL表示旅行表示旅行 1-2-3-4-11-2-3-4-1

• 树中叶节点的数目(树中叶节点的数目( n-1n-1 )) !!

23/4/21 18

Page 19: Chapter16  回溯

n=4n=4 时,旅行商问题的求解过程时,旅行商问题的求解过程

路径路径 耗费耗费1234112341 5959

1243112431 6666

1324113241 2525

【【限界函数限界函数】】如果目前建立的部分的费用大于或等如果目前建立的部分的费用大于或等于当前最佳路径的费用,则杀死当前节点。于当前最佳路径的费用,则杀死当前节点。

例如:到达例如:到达 II 时,部分旅行耗费时,部分旅行耗费 1,3,41,3,4 的耗费为的耗费为26>2526>25 ,所以,搜索以,所以,搜索以 II 为根节点的子树毫无意义。为根节点的子树毫无意义。

23/4/21 19

Page 20: Chapter16  回溯

回溯算法的解空间形式回溯算法的解空间形式• 子集树:当问题解空间树是子集树:当问题解空间树是 nn 个元素的一个子集时,例如:个元素的一个子集时,例如:

0/10/1 背包问题背包问题– 子集树有子集树有 22nn 个叶节点,遍历耗时 个叶节点,遍历耗时 ΩΩ(2(2nn) )

• 排列树:当问题解空间树是排列树:当问题解空间树是 nn 个元素的一个排列时,例如:个元素的一个排列时,例如:旅行商问题旅行商问题– 排列树有排列树有 n!n! 个叶节点,遍历耗时 个叶节点,遍历耗时 ΩΩ(n!) (n!)

23/4/21 20

Page 21: Chapter16  回溯

回溯算法小结回溯算法小结• 步骤:步骤:

定义一个解空间,它包含问题的解;定义一个解空间,它包含问题的解; 用适于搜索的方式组织该空间;用适于搜索的方式组织该空间; 用用 DFSDFS 法搜索该空间,并使用限界函数加速对最优法搜索该空间,并使用限界函数加速对最优

解的搜索,避免不必要的移动解的搜索,避免不必要的移动• 在搜索期间的任何时刻,仅保留从开始节点到当前在搜索期间的任何时刻,仅保留从开始节点到当前 EE 节点的路径,节点的路径,因此,回溯算法的空间需求为因此,回溯算法的空间需求为

– OO (从开始节点起最长路径的长度);(从开始节点起最长路径的长度);• 解空间的大小是该长度的指数或阶乘!解空间的大小是该长度的指数或阶乘!————全部存储解空间,不够全部存储解空间,不够

用。用。

23/4/21 21

Page 22: Chapter16  回溯

33 、回溯算法的应用、回溯算法的应用货箱装船问题:子集树货箱装船问题:子集树旅行商问题:排列树旅行商问题:排列树

23/4/21 22

Page 23: Chapter16  回溯

(( 11 )货箱装船问题)货箱装船问题

• 有两艘船,有两艘船, nn 个货箱。第一艘船的载重量是个货箱。第一艘船的载重量是 c1 c1 ,第二艘船的载,第二艘船的载重量是重量是 c2c2 ,, WiWi 是货箱是货箱 i i 的重量且的重量且

寻求一种将寻求一种将 nn 个货箱全部装船的方法个货箱全部装船的方法

• 例如:当例如:当 n= 3n= 3 ,, c1 =c2 = 50c1 =c2 = 50 ,, w=[10,40,40]w=[10,40,40] ;可将货箱;可将货箱 1 , 21 , 2 装到装到第一艘船上,货箱第一艘船上,货箱 33 装到第二艘船上。装到第二艘船上。

• 再如:再如: w= [20 , 40 , 40]w= [20 , 40 , 40] ,结果如何?,结果如何?

n

i

CCWi1

21

Page 24: Chapter16  回溯

解决策略解决策略• 存在一种方法能够装载所有存在一种方法能够装载所有 nn 个货箱时,可以验证以下个货箱时,可以验证以下

的装船策略可以获得成功: 的装船策略可以获得成功: • 1) 1) 尽可能地将第一艘船装至它的重量极限尽可能地将第一艘船装至它的重量极限• 2) 2) 将剩余货箱装到第二艘船将剩余货箱装到第二艘船• 为了尽可能地将第一艘船装满,需要选择一个货箱的子为了尽可能地将第一艘船装满,需要选择一个货箱的子

集,它们的总重量尽可能接近集,它们的总重量尽可能接近 cc11

23/4/21 24

Page 25: Chapter16  回溯

第一种回溯算法第一种回溯算法

• 思想:寻找 即寻找思想:寻找 即寻找一个重量的子集尽量接近一个重量的子集尽量接近 cc11 。。

• 限界函数:定义 表示节点限界函数:定义 表示节点 OO 的当前重量;的当前重量;– 若若 cw>ccw>c11 ,则表示以,则表示以 OO 为根的子树不能产生一个可行为根的子树不能产生一个可行

的解答,避免移动。的解答,避免移动。

]1,0[max11

ixc

ixiw

ixiw

n

i

n

i

,,其中

n

iixiwcw

1

Page 26: Chapter16  回溯

n=4n=4 时,求解过程时,求解过程w=[8w=[8 ,, 66 ,, 22 ,, 3]3] , , C1=12C1=12

cw=8cw=8

cw=10cw=10

cw=8cw=8

cw=11cw=11

最优解最优解 x: [1,0,0,1]x: [1,0,0,1]

23/4/21 26

Page 27: Chapter16  回溯

第一种回溯算法第一种回溯算法 -- 代码分析代码分析• Page498Page498 :程序:程序 16-116-1• 注意:一个可行节点的右孩子总是可行注意:一个可行节点的右孩子总是可行• 时间复杂度:时间复杂度: O(2O(2nn) ) • 递归栈空间:递归栈空间: O(n) O(n)

23/4/21 27

Page 28: Chapter16  回溯

第二种回溯算法:优化第二种回溯算法:优化• 如果当前节点的右子树不可能包含比当前最优解更好的解如果当前节点的右子树不可能包含比当前最优解更好的解

时,就不移动到右子树上!时,就不移动到右子树上!• 设设 bestwbestw 为当前最优解,为当前最优解, ZZ 为解空间树的第为解空间树的第 i i 层的一个节层的一个节

点点• 限界函数: 为剩余货箱的重量; 当限界函数: 为剩余货箱的重量; 当

cw+r<=bestwcw+r<=bestw 时,没有必要去搜索时,没有必要去搜索 Z Z 的右子树的右子树• Page499Page499 :程序:程序 16-216-2

n

ij

jwr1

][

Page 29: Chapter16  回溯

寻找最优子集寻找最优子集• Page500Page500 :程序:程序 16-316-3• 引入引入 bestxbestx ,记录当前找到的最优货箱子集,记录当前找到的最优货箱子集• 时间复杂度:时间复杂度: O(n2O(n2nn))• 降低复杂度的两种方法:降低复杂度的两种方法: Page501Page501

23/4/21 29

Page 30: Chapter16  回溯

(( 22 )旅行商问题)旅行商问题• 解空间是排列树解空间是排列树• 可采用可采用 Page8Page8 的的 PermPerm 函数,函数,

产生产生 nn 个元素表的所有排列个元素表的所有排列

作为类作为类 AdjacencyWDigraphAdjacencyWDigraph 的成的成员员

23/4/21 30

Page 31: Chapter16  回溯

使用递归函数生成排列(使用递归函数生成排列( P7 P7 例例 1-1-33 ))

【【例例】】 a,b,ca,b,c 的排列方式有:的排列方式有: abcabc ,, acbacb ,, bacbac ,, bcabca ,, cabcab ,,cbacba 。共。共 66 种(种( nn 个元素的排列方式共有个元素的排列方式共有 nn!种)!种)• 令令 E{e1E{e1 ,,……,, en}en}表示表示 nn 个元素的集合。个元素的集合。• 令令 EiEi 为移去元素为移去元素 ii 后所得的集合,后所得的集合,• perm(X)perm(X) 表示集合表示集合 XX 中元素的排列方式,中元素的排列方式,• ei.perm(X)ei.perm(X) 表示在表示在 perm(X)perm(X) 中的每个排列方式的前面均加上中的每个排列方式的前面均加上eiei 以后所得到的排列方式。以后所得到的排列方式。

例如,若例如,若 E={a,b,c}E={a,b,c} ,则,则 E1={b,c},perm(E1)={bc,cb},E1={b,c},perm(E1)={bc,cb},

e1.perm(E1)={abc,acb}e1.perm(E1)={abc,acb}

23/4/21 31

Page 32: Chapter16  回溯

使用递归函数生成排列(使用递归函数生成排列( P7 P7 例例 1-1-33 ))

【【递归出口递归出口】】 n=1n=1 。当只有一个元素时,只可能产生一种排。当只有一个元素时,只可能产生一种排列方式,即列方式,即 perm(E)=eperm(E)=e ,其中,其中 ee 是是 EE 中唯一的元素。中唯一的元素。当当 n>1n>1 时,时, perm(E)perm(E)

=e1.perm(E1)+e2.perm(E2)+e3.perm(E3)+…en.perm(En)=e1.perm(E1)+e2.perm(E2)+e3.perm(E3)+…en.perm(En)

即采用即采用 nn 个个 perm(X)perm(X) 来定义来定义 perm(E)perm(E) ,其中每个,其中每个 XX 包含包含 n-1n-1个元素。个元素。

【【例例】】当当 n=3n=3 ,并且,并且 E={aE={a ,, bb ,, c}c}

则,则, perm(E)=a.perm({b,c})+b.perm({a,c})+c.perm({a,b})perm(E)=a.perm({b,c})+b.perm({a,c})+c.perm({a,b})

perm({b,c})=b.perm(c)+c.perm(b)perm({b,c})=b.perm(c)+c.perm(b)

a.perm({b,c})=ab.perm(c)a.perm({b,c})=ab.perm(c)+ac.perm(b)=ab.c+ac.b=(abc,acb)+ac.perm(b)=ab.c+ac.b=(abc,acb)

23/4/21 32

Page 33: Chapter16  回溯

使用递归函数生成排列(使用递归函数生成排列( P7 P7 例例 1-1-33 ))

a.perm({b,c})a.perm({b,c}) 包含两个排列式:包含两个排列式: abcabc 和和 acbacb ,,

aa 是它们的前缀,是它们的前缀, perm({b,c})perm({b,c}) 是它们的后缀是它们的后缀

同样,同样, ac.perm({b})ac.perm({b}) 表示前缀表示前缀 acac ,后缀为,后缀为 perm({b})perm({b}) 的排的排列方式。列方式。

程序程序 1-101-10输出所有前缀为输出所有前缀为 list[0:k-1]list[0:k-1] ,后缀为,后缀为 list[k,m]list[k,m] 的排的排列方式。列方式。

23/4/21 33

Page 34: Chapter16  回溯

使用递归函数生成排列(程序使用递归函数生成排列(程序 1-1-1010 ))

template<class T>template<class T>

void Perm(T list[], int k, int m)void Perm(T list[], int k, int m)

{// Generate all permutations of list[k:m].{// Generate all permutations of list[k:m].

int i;int i;

if (k == m) if (k == m)

{ // { // 输出一个排列方式输出一个排列方式 for (i = 0; i <= m; i++)for (i = 0; i <= m; i++)

cout << list[i];cout << list[i];

cout << endl;cout << endl;

}}

23/4/21 34

Page 35: Chapter16  回溯

使用递归函数生成排列(程序使用递归函数生成排列(程序 1-1-1010 ))

else // list[k:m] has more than one permutationelse // list[k:m] has more than one permutation

// generate these recursively // generate these recursively

for (i = k; i <= m; i++) for (i = k; i <= m; i++)

{{

Swap(list[k], list[i]);Swap(list[k], list[i]);

Perm(list, k+1, m);Perm(list, k+1, m);

Swap(list[k], list[i]);Swap(list[k], list[i]);

}}

}}

23/4/21 35

Page 36: Chapter16  回溯

预处理程序:预处理程序: TSPTSPtemplate<class T>template<class T>T AdjacencyWDigraph<T>::TSP(int v[ ])T AdjacencyWDigraph<T>::TSP(int v[ ]){{ x = new int [n+1]; x = new int [n+1]; 保存到当前节点的路径保存到当前节点的路径 for (int i = 1; i <= n; i++) x[i] = i;for (int i = 1; i <= n; i++) x[i] = i; bestc = NoEdge;bestc = NoEdge; bestx = v; bestx = v; 保存最优解路径保存最优解路径 cc = 0;cc = 0; tSP(2); tSP(2); 搜索搜索 x[2:n]x[2:n] 的各种排列的各种排列 delete [] x;delete [] x; return bestc; return bestc; 返回最优解耗费返回最优解耗费}}

23/4/21 36

Page 37: Chapter16  回溯

tSPtSP 函数函数结构与结构与 PermPerm 函数相同。函数相同。•当当 i=ni=n 时,处在排列树的叶节点的父节点上,并且需要验证时,处在排列树的叶节点的父节点上,并且需要验证从从 x[n-1]x[n-1] 到到 x[n]x[n] 有一条边,从有一条边,从 x[n]x[n] 到起点到起点 x[1]x[1] 也有一条边。也有一条边。若两边都存在,则发现一个新旅行。若发现的旅行是目前发若两边都存在,则发现一个新旅行。若发现的旅行是目前发现的最优旅行,则将旅行和它的耗费分别存入现的最优旅行,则将旅行和它的耗费分别存入 bestxbestx 和和 bestcbestc中。中。•当当 i<ni<n 时,检查当前时,检查当前 i-1i-1 层节点的孩子节点,并且仅当以下情层节点的孩子节点,并且仅当以下情况出现时,移动到孩子节点之一:况出现时,移动到孩子节点之一:

•(( 11 )有从)有从 x[i-1]x[i-1] 到到 x[i]x[i] 的一条边(如果是的话,的一条边(如果是的话, x[1:i]x[1:i]定义了网络中的一条路径);定义了网络中的一条路径);•(( 22 )路径)路径 x[1:i]x[1:i] 的耗费小于当前的最优解的耗费的耗费小于当前的最优解的耗费 ..

变量变量 cccc 保存目前所构造的路径的耗费。保存目前所构造的路径的耗费。23/4/21 37

Page 38: Chapter16  回溯

迭代回溯算法:迭代回溯算法: tSPtSPtemplate<class T> a[N][N]template<class T> a[N][N] 表示两个节点之间是否有边表示两个节点之间是否有边void AdjacencyWDigraph<T>::tSP(int i)void AdjacencyWDigraph<T>::tSP(int i){{ if (i == n) if (i == n) 位于叶子节点的父节点位于叶子节点的父节点 {{ if (a[x[n-1]][x[n]] != NoEdge && a[x[n]][1] != NoEdge && (cc + a[x[n-if (a[x[n-1]][x[n]] != NoEdge && a[x[n]][1] != NoEdge && (cc + a[x[n-

1]][x[n]] + a[x[n]][1] < bestc || bestc == NoEdge)) 1]][x[n]] + a[x[n]][1] < bestc || bestc == NoEdge)) { { 找到更优的旅行路径找到更优的旅行路径 for (int j = 1; j <= n; j++) bestx[j] = x[j];for (int j = 1; j <= n; j++) bestx[j] = x[j]; bestc = cc + a[x[n-1]][x[n]] + a[x[n]][1];bestc = cc + a[x[n-1]][x[n]] + a[x[n]][1]; }} }}

23/4/21 38

Page 39: Chapter16  回溯

迭代回溯算法:迭代回溯算法: tSP cont.tSP cont.else {else { for (int j = i; j <= n; j++) for (int j = i; j <= n; j++) 判断是否能移到子树判断是否能移到子树 x[j]x[j] if (a[x[i-1]][x[j]] != NoEdge &&if (a[x[i-1]][x[j]] != NoEdge && (cc + a[x[i-1]][x[i]] < bestc || bestc == NoEdge)) (cc + a[x[i-1]][x[i]] < bestc || bestc == NoEdge)) { { 类类 permperm 的排列法搜索的排列法搜索 Swap(x[i], x[j]);Swap(x[i], x[j]); cc += a[x[i-1]][x[i]];cc += a[x[i-1]][x[i]]; tSP(i+1);tSP(i+1); cc -= a[x[i-1]][x[i]];cc -= a[x[i-1]][x[i]]; Swap(x[i], x[j]);Swap(x[i], x[j]); }} }}}}

23/4/21 39

Page 40: Chapter16  回溯

本章小结本章小结• 回溯算法的基本思想回溯算法的基本思想• 限界函数的使用限界函数的使用• 回溯算法的应用回溯算法的应用

货箱装船货箱装船 旅行商问题旅行商问题

23/4/21 40

Page 41: Chapter16  回溯

复杂问题解法的提示复杂问题解法的提示• 很多情况下,我们需要找到某个问题的候选集的一个子很多情况下,我们需要找到某个问题的候选集的一个子

集或者一种排列集或者一种排列• 这些求解过程通常需要满足一定的约束条件,并且要优这些求解过程通常需要满足一定的约束条件,并且要优化一些目标函数化一些目标函数

• 通常解法:将解空间组织成一棵树,并通过对这棵树的通常解法:将解空间组织成一棵树,并通过对这棵树的系统性搜索,以获取问题的解系统性搜索,以获取问题的解

23/4/21 41

Page 42: Chapter16  回溯

子集问题子集问题• 求解过程是寻找求解过程是寻找 nn 个元素的一个子集 个元素的一个子集 • 子集必须满足一定约束条件,并且尽可能地优化某些目子集必须满足一定约束条件,并且尽可能地优化某些目标函数标函数

• 应用示例应用示例 PartitionPartition Subset sumSubset sum 0/10/1 背包背包 Satisfiability (find subset of variables to be set Satisfiability (find subset of variables to be set

to true so that formula evaluates to true).to true so that formula evaluates to true).

23/4/21 42

Page 43: Chapter16  回溯

子集问题的解空间子集问题的解空间• 当要求解的问题需要根据当要求解的问题需要根据 nn 个元素的一个子集来优化某些函数时,解个元素的一个子集来优化某些函数时,解

空间树被称作子集树(空间树被称作子集树( Subset TreeSubset Tree )。)。• 对有对有 nn 个对象的个对象的 0/10/1 背包问题来说,它的解空间就是一个子集树。背包问题来说,它的解空间就是一个子集树。• 一棵树有一棵树有 22nn 个叶节点,全部节点有个叶节点,全部节点有 22n+1n+1-1-1 个。个。• 每一个对树中所有节点进行遍历的算法都必须耗时每一个对树中所有节点进行遍历的算法都必须耗时 ΩΩ(2(2nn)) 。。

23/4/21 43

Page 44: Chapter16  回溯

排列问题排列问题

• 求解过程是寻找求解过程是寻找 nn 个元素的一个排列个元素的一个排列• 排列必须满足一定约束条件,并且尽可能地优化某些目标排列必须满足一定约束条件,并且尽可能地优化某些目标

函数函数• 应用示例应用示例

TSPTSP :旅行商问题:旅行商问题 N-N- 皇后问题皇后问题

23/4/21 44

Page 45: Chapter16  回溯

排列问题的解空间排列问题的解空间• 当要求解的问题需要根据一个当要求解的问题需要根据一个 nn 个元素的排列来优化某些函数时,个元素的排列来优化某些函数时,

解空间树被称作排列树(解空间树被称作排列树( Permutation TreePermutation Tree )。)。• 这样的树有这样的树有 n!n! 个叶节点;个叶节点;• 所以每一个遍历树中所有节点的算法都必须耗时所以每一个遍历树中所有节点的算法都必须耗时 ΩΩ(n!)(n!) 。。

23/4/21 45