《算法设计与分析》-第五章 回溯法

合集下载

算法设计与分析——批处理作业调度(回溯法)

算法设计与分析——批处理作业调度(回溯法)

算法设计与分析——批处理作业调度(回溯法)之前讲过⼀个相似的问题流⽔作业调度问题,那⼀道题最开始⽤动态规划,推到最后得到了⼀个Johnson法则,变成了⼀个排序问题,有兴趣的可以看⼀下本篇博客主要参考⾃⼀、问题描述给定n个作业的集合{J1,J2,…,Jn}。

每个作业必须先由机器1处理,然后由机器2处理。

作业Ji需要机器j的处理时间为t ji。

对于⼀个确定的作业调度,设Fji是作业i在机器j上完成处理的时间。

所有作业在机器2上完成处理的时间和称为该作业调度的完成时间和。

批处理作业调度问题要求对于给定的n个作业,制定最佳作业调度⽅案,使其完成时间和达到最⼩。

例:设n=3,考虑以下实例:看到这⾥可能会对这些完成时间和是怎么计算出来的会有疑问,这⾥我拿123和312的⽅案来说明⼀下。

对于调度⽅案(1,2,3)作业1在机器1上完成的时间是2,在机器2上完成的时间是3作业2在机器1上完成的时间是5,在机器2上完成的时间是6作业3在机器1上完成的时间是7,在机器2上完成的时间是10所以,作业调度的完成时间和= 3 + 6 + 10这⾥我们可以思考⼀下作业i在机器2上完成的时间应该怎么去求?作业i在机器1上完成的时间是连续的,所以是直接累加就可以。

但对于机器2就会产⽣两种情况,这两种情况其实就是上图的两种情况,对于(1,2,3)的调度⽅案,在求作业2在机器2上完成的时间时,由于作业2在机器1上还没有完成,这就需要先等待机器1处理完;⽽对于(3,1,2)的调度⽅案,在求作业2在机器2上完成的时间时,作业2在机器1早已完成,⽆需等待,直接在作业1被机器1处理之后就能接着被处理。

综上,我们可以得到如下表达式if(F2[i-1] > F1[i])F2[i] = F2[i-1] + t[2][i]elseF2[i] = F1[i] + t[2][i]⼆、算法设计类Flowshop的数据成员记录解空间的结点信息,M输⼊作业时间,bestf记录当前最⼩完成时间和,数组bestx记录相应的当前最佳作业调度。

《算法设计与分析》-回溯

《算法设计与分析》-回溯

从n个元素的集合S中找出满 足某种性质的子集时
子集树 解空间大小: 2n
确定n个元素满足某 种性质的排列时
Add text in here too Add text in here
排列树 解空间大小: n!
满足约束条件的解,解 空间中的一个子集
可行解
最优解
可行解和 最优解
使目标函数取极值(极 大或极小)的可行解, 一个或少数几个
算法效率
如果不考虑计算当前圆排列中各圆的圆心横坐 标和计算当前圆排列长度所需的计算时间按,则 Backtrack需要O(n!)计算时间。由于算法Backtrack 在最坏情况下需要计算O(n!)次圆排列长度,每次 计算需要O(n)计算时间,从而整个算法的计算时间 复杂性为O((n+1)!) 上述算法尚有许多改进的余地。例如,像 1,2,…,n-1,n和n,n-1, …,2,1这种互为镜像的排列具 有相同的圆排列长度,只计算一个就够了,可减少 约一半的计算量。另一方面,如果所给的n个圆中 有k个圆有相同的半径,则这k个圆产生的k!个完全 相同的圆排列,只计算一个就够了。
算法设计
圆排列问题的解空间是一棵排列树。按照回溯法搜索排列树 的算法框架,设开始时a=[r1,r2,……rn]是所给的n个元的半 径,则相应的排列树由a[1:n]的所有排列构成。 解圆排列问题的回溯算法中,CirclePerm(n,a)返回找到 的最小的圆排列长度。初始时,数组a是输入的n个圆的半径 ,计算结束后返回相应于最优解的圆排列。center计算圆在 当前圆排列中的横坐标,由x^2 = sqrt((r1+r2)^2-(r1-r2)^2) 推导出x = 2*sqrt(r1*r2)。Compoute计算当前圆排列的长度 。变量min记录当前最小圆排列长度。数组r表示当前圆排列 。数组x则记录当前圆排列中各圆的圆心横坐标。 在递归算法Backtrack中,当i>n时,算法搜索至叶节点,得 到新的圆排列方案。此时算法调用Compute计算当前圆排列 的长度,适时更新当前最优值。 当i<n时,当前扩展节点位于排列树的i-1层。此时算法选 择下一个要排列的圆,并计算相应的下界函数。

回溯法_ppt课件

回溯法_ppt课件
//h(i)表示在当前扩展节点处x[t]的第i个可选值
实 现 递 归
} }
if (Constraint(t) &&Bound(t) ) { if (Solution(t)) Output(x); else t ++; } else t --;
if (Constraint(t) &&Bound(t) ) { if (Solution(t)) Output(x); else t ++; } else t --; 分析:
算法设计与分析 >回溯法
5、回溯法解题步骤: 1).针对所给问题,定义问题的解空间 2).确定解空间结构. 3).以深度优先方式搜索解空间.
算法模式 Procedure BACKTRACK(n); {k:=l; repeat if TK (x1,x2,...xK-1 )中的值未取遍 then { xK:=TK (x1,x2,..., x K-1 )中未取过的一个值; if BK (x1, x2, ..., x K) then //状态结点(x1,...xk)被激活 if k=n then output(x1, x2, ..., xk) //输出度优先 e1se k:=k-l; //回溯 until k=0; end;{BACKTRACK}
if (Constraint(t)&&Bound(t) ) Backtrack(t + 1); if语句含义:Constraint(t)和Bound(t)表示当前扩展 节点处的约束函数和限界函数。 Constraint(t): 返回值为true时,在当前扩展节点处 x[1:t]的取值问题的约束条件,否则不满足问题的约束条 件,可剪去相应的子树 Bound(t): 返回的值为true时,在当前扩展节点处 x[1:t]的取值为时目标函数越界,还需由Backtrack(t+1) 对其相应的子树做进一步搜索。否则,当前扩展节点处 x[1:t]的取值是目标函数越界,可剪去相应的子树 for循环作用:搜索遍当前扩展的所有未搜索过的 子树。 递归出口:Backtrack(t)执行完毕,返回t-1层继续 执行,对还没有测试过的x[t-1]的值继续搜索。当t=1时, 若以测试完x[1]的所有可选值,外层调用就全部结束。

算法分析与设计实验报告--回溯法

算法分析与设计实验报告--回溯法

算法分析与设计实验报告--回溯法实验目的:通过本次实验,掌握回溯法的基本原理和应用,能够设计出回溯法算法解决实际问题。

实验内容:1.回溯法概述回溯法全称“试探回溯法”,又称“逐步退化法”。

它是一种通过不断试图寻找问题的解,直到找到解或者穷尽所有可能的解空间技术。

回溯法的基本思路是从问题的某一个初始状态开始,搜索可行解步骤,一旦发现不满足求解条件的解就回溯到上一步,重新进行搜索,直到找到解或者所有可能的解空间已经搜索完毕。

2.回溯法的基本应用回溯法可用于求解许多 NP 问题,如 0/1 背包问题、八皇后问题、旅行商问题等。

它通常分为两种类型:一种是通过枚举所有可能的解空间来寻找解;另一种则是通过剪枝操作将搜索空间减少到若干种情况,大大减少了搜索时间。

3.回溯法的解题思路(1)问题分析:首先需要对问题进行分析,确定可行解空间和搜索策略;(2)状态表示:将问题的每一种状况表示成一个状态;(3)搜索策略:确定解空间的搜索顺序;(4)搜索过程:通过逐步试探,不断扩大搜索范围,更新当前状态;(5)终止条件:在搜索过程中,如果找到了满足要求的解,或者所有的可行解空间都已搜索完毕,就结束搜索。

4.八皇后问题八皇后问题是指在一个 8x8 的棋盘上放置八个皇后,使得任意两个皇后都不在同一行、同一列或同一对角线上。

通过回溯法可以求解出所有的可能解。

实验过程:回溯法的实现关键在于搜索空间的剪枝,避免搜索无用的解;因此,对于八皇后问题,需要建立一个二维数组来存放棋盘状态,以及一个一维数组来存放每行放置的皇后位置。

从第一行开始搜索,按照列的顺序依次判断当前的空位是否可以放置皇后,如果可以,则在相应的位置标记皇后,并递归到下一行;如果不能,则回溯到上一行,重新搜索。

当搜索到第八行时,获取一组解并返回。

代码实现:```pythondef is_valid(board, row, col):for i in range(row):if board[i] == col or abs(board[i] - col) == abs(i - row):return Falsereturn True实验结果:当 n=4 时,求得的所有可行解如下:```[[1, 3, 0, 2],[2, 0, 3, 1]]```本次实验通过实现回溯法求解八皇后问题,掌握了回溯法的基本原理和应用,并对回溯法的核心思想进行了深入理解。

算法设计与分析——回溯法

算法设计与分析——回溯法

任意两个皇后不允许处在同一与棋盘边框成 45°角的斜线上,设置 数组,若a的第 个数字为 数组, 的第k个数字为 °角的斜线上,设置g数组 的第 x,则g(k)=x。要求解的 位数的第 个数字与 位数的第j个数字与 , ( ) 。要求解的8位数的第 个数字的绝对值不等于j )。若 第k个数字的绝对值不等于 – k(设置 > k)。若 个数字的绝对值不等于 (设置j )。 出现: 出现:
当问题所涉及数量非常大时, 当问题所涉及数量非常大时,穷举的工作量 也就相应较大,程序运行时间也就相应较长。 也就相应较大,程序运行时间也就相应较长。为 应用穷举求解时, 此,应用穷举求解时,应根据问题的具体情况分 析归纳,寻找简化规律,精简穷举循环, 析归纳,寻找简化规律,精简穷举循环,优化穷 举策略。 举策略。
与穷举法相比,回溯法的“聪明” 与穷举法相比,回溯法的“聪明”之处在于能 适时“回头” 若再往前走不可能得到解, 适时“回头”,若再往前走不可能得到解,就回溯 退一步另找线路,这样可省去大量的无效操作。 退一步另找线路,这样可省去大量的无效操作。 因此,回溯和穷举相比,回溯更适宜于量比较大, 因此,回溯和穷举相比,回溯更适宜于量比较大, 候选解比较多的问题。 候选解比较多的问题。
printf("\n"); } void tackle(int i) { int j; for(j=1;j<=n;j++) { //列数的移动 if( (b[j]==0) && (c[i+j]==0) && (d[i-j+n]==0) ) { a[i]=j; //记录下该行的可放列 b[j]=1; //表示该列被占 c[i+j]=1; //表示某斜率为1的对角线被占 d[i-j+n]=1; //表示某斜率为-1的对角线被占 if(i<n)

计算机算法设计与分析第5章 回溯算法PPT课件

计算机算法设计与分析第5章 回溯算法PPT课件
注意:同一个问题可以有多种表示,有些 表示方法更简单,所需表示的状态空间更 小(存储量少,搜索方法简单)。
22.09.2020
15
5.1.1 问题的解空间
为了用回溯法求解一个具有n个输入的问题,一 般情况下,将其可能解表示为满足某个约束条 件的等长向量X=(x1, x2, …, xn),其中分量xi (1≤i≤n) 的取值范围是某个有限集合Si={ai1, ai2, …, airi}, 所有可能的解向量构成了问题的解空间。
22.09.2020
2
提纲
一、回溯法的算法框架 二、装载问题 三、n后问题 四、0-1背包问题 五、最大团问题 六、图的m着色问题 七、旅行售货员问题
22.09.2020
3
提纲
一、回溯法的算法框架 二、装载问题 三、n后问题 四、0-1背包问题 五、最大团问题 六、图的m着色问题 七、旅行售货员问题
17
2 旅行售货员问题
问题描述:某售货员 要到若干城市去推销 商品,一直各城市之 间的路程,他要选定 一条从驻地出发,经 过每个城市一遍,最 后回到住地的路线, 使总的路程最短。
(a) 二维搜索空间无解
(b) 三维搜索空间的解
错误的解空间将不能搜索到正确答案!
22.09.2020
13
5.1.1 问题的解空间
对于任何一个问题,可能解的表示方式和它相应的 解释隐含了解空间及其大小。
例如,对于有n个物品的0/1背包问题,其可能解的 表示方式可以有以下两种:
(1)可能解由一个不等长向量组成,当物品i(1≤i≤n)装入 背包时,解向量中包含分量i,否则,解向量中不包含分 量i,当n=3时,其解空间是:
计算机算法设计与分析
Design and Analysis of Computer Algorithms

算法设计与分析 第2版 第5章-回溯法

算法设计与分析 第2版 第5章-回溯法
实际上,有些问题的解空间因过于复杂或状态过多难以画出来。
5.1.2 什么是回溯法
在包含问题的所有解的解空间树中,按照深度优先搜索的策略, 从根结点(开始结点)出发搜索解空间树。
当从状态si搜索到状态si+1后,如果si+1变为死结点,则从状态si+1 回退到si,再从si找其他可能的路径,所以回溯法体现出走不通就退回 再走的思路。
10
LM
G
10
NO
{a,b,c} {a,b} {a, c} {a} {b,c} {b} {c} { }
排列树:当所给的问题是确定n个元素满足某种性质的排列时,相应
的解空间树称为排列树。
注意:问题的解空间树是虚拟的,并不需要在算法运行时构造一棵
真正的树结构,然后再在该解空间树中搜索问题的解,而是只存储从根结 点到当前结点的路径。
输出结果;
else
{ for (j=下界;j<=上界;j++) //用j枚举i所有可能的路径
{ x[i]=j;
//产生一个可能的解分量

//其他操作
if (constraint(i) && bound(i))
backtrack(i+1);
//满足约束条件和限界函数,继续下一层
}
}
}
【例5.3】有一个含n个整数的数组a,所有元素均不相同,设
输出x;
else i++;
//进入下一层次
}
}
}
else i--;
//回溯:不存在子结点,返回上一层
}
}
2. 递归的算法框架
(1)解空间为子集树
int x[n];

第五章 回溯法1--基本概念--n后问题

第五章    回溯法1--基本概念--n后问题
1 6 4 3 20 4 3 30 5 A A 2 10 2 1
B
3 4
C
4 G G 3 M M 2 H H 4 N N
D D
4 26>25 2 I I 3 P P 2 J J
E
3
图1 四个顶点的带权图
F
4 L L 59
K
2 Q Q
O
60+6>59 25
第五章 回溯法
19+6=25 29+30>25
活结点 当前扩展结点 死结点 D B 1 A
0 1 F 0
K
45
1
0
E
C 0 G 0 1 N
25
死结点 1
1
H
0
I
1
J
0 O
0
4
L
50
M
25
图5-2 在0-1背包问题的解空间树上搜索最优解
第五章 回溯法
例2:旅行售货员问题:某售货员要到若干城市推销商 品,已知各城市间的路程(或旅费)。他要选一条从 驻地出发,经过每个城市一遍,最后回到驻地的路线 使总的路程(总的旅费)最小。
第五章 回溯法 2
2. 解空间树
通常把解空间组织成解空间树。 例如:对于n=3时的0-1背包问题,其解空间用一 棵完全二叉树表示,如下图所示。
1
A
0
B
1 0 1
C
0
D 1 H
0 1
E
0
F
1 0 1
G
0
I
J
K
L
M
N
O
0-1背包问题的解空间树
第五章 回溯法
3
3. 搜索解空间树的过程
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

n后问题算法的描述如下:
1. void n_queens(int n,int x[]) 2. { 3. int k = 1; /* k:搜索深度 */ : 4. x[1] = 0; 5. while (k>0) { 6. x[k] = x[k] + 1; /* 在当前列加 的位置开始搜索 */ 在当前列加1的位置开始搜索 7. while ((x[k]<=n)&&(!place(x,k))) /* 当前列位置是否满足条件 */ 8. x[k] = x[k] + 1; /* 不满足条件 继续搜索下一列位置 */ 不满足条件,继续搜索下一列位置 9. if (x[k]<=n) { /* 存在满足条件的列 */ 存在满足条件的列? 10. if (k==n) break; /* 是最后一个皇后 完成搜索 */ 是最后一个皇后,完成搜索 11. else { 12. k = k + 1; x[k] = 0; /* 不是 则处理下一个行皇后 */ 不是,则处理下一个行皇后 13. } 14. } 15. else { /* 已判断完 列,均没有满足条件 */ 已判断完n列 均没有满足条件 16. x[k] = 0; k = k – 1; /* 第k行复位为 回溯到前一行 */ 行复位为0,回溯到前一行 行复位为 17. } 18. } 19. }

}
5.2 回溯法的算法框架
用回溯法搜索排列树的一般解法:
– –
Void traceback(int t) {
If(t>n) output(x); Else for(i=t;i<=n;i++){ swap(x[t],x[i]); if(constraint(t)&&bound(t)) backtrack(t+1); swap(x[i],x[t]); }
5.1 回溯法的基本思想
(2)状态空间树:问题解空间的树形式表示 例:n=3, 0/1背包问题的状态空间树.
1 1 D 1 H 0 I 1 J B 0 E 0 K 1 L 1 F M 1 N A 0 C 0 G 0 O
----子集树 解空间大小: 2n
5.1 回溯法的基本思想
(2)状态空间树:问题解空间的树形式表示 例:n=4, 旅行商问题的状态空间树.
void backtrack(int i){ if(i>n){ if(cw>bestw) bestw=cw; return; } if(cw+w[i]<=c){ cw+=w[i]; backtrack(i+1); cw-=w[i]; } backtrack(i+1); }
5.5 回溯法的应用 回溯法的应用—0/1背包问题 背包问题
回溯法(backtracking) 第五章 回溯法
5.1 回溯法的基本思想 5.2 回溯法的算法框架 5.3 回溯法的应用—n后问题 5.4 回溯法的应用—装载问题
回溯法(Backtracking) 第五章 回溯法
回溯法和分支限界法都是通过系统地搜索解空 间树而求得问题解的搜索算法. 在系统地检查解空间的过程中,抛弃那些不可 能导致合法解的候选解,从而使求解时间大大 缩短.(与蛮干算法相区别) 回溯法以深度优先的方式搜索解空间,而分支 限界法以广度优先或最小耗费(最大收益)的 方式搜索解空间.
}

}
5.2 回溯法的算法框架
用回溯法搜索子集树的一般解法:
– –
Void backtrack(int t) {
If(t>n) output(x); Else for(i=0;i<=1;i++){ x[t]=i; if(constraint(t)&&bound(t)) backtrack(t+1); }
A 2 C 3 F 4 L 4 2 G H 3 4 M N 1 B 3 D
4 4 I 2 O E 2 J 3 P 3 K 2 Q
----排列树 解空间大小: n!
5.1 回溯法的基本思想
(3)状态空间树的动态搜索
可行解和最优解: 可行解:满足约束条件的解,解空间中的一个子集 最优解:使目标函数取极值(极大或极小)的可行解,一 个或少数几个 例:货郎担问题,有nn种可能解. n!种可行解,只有一个或 几个解是最优解. 例:背包问题,有2n种可能解,有些是可行解,只有一个或 几个是最优解. 有些问题,只要可行解,不需要最优解,例如八后问题.
}
5.4 回溯法的应用 装载问题 回溯法的应用—装载问题
有一批集装箱要装上一艘载重量为c的轮船. 其中集装箱i的重量为Wi.最优装载问题要求 确定在装载体积不受限制的情况下,将尽可能 多的集装箱装上轮船.
int n,w[],c,cw,bestw; int maxloading(){ cw=0;bestw=0; backtrack(1); return bestw; }
5.1 回溯法的基本思想
回溯法(backtracking)是一种系统地搜索问 题解的方法.为实现回溯,首先需要定义一个 解空间(solution space),然后以易于搜索 的方式组织解空间,最后用深度优先的方法搜 索解空间,获得问题的解.
5.1 回溯法的基本思想
回溯法求解的三个步骤: (1)定义一个解空间,它包含问题的解 (2)用易于搜索的方式组织解空间 (3)深度优先搜索解空间,获得问题的解.
5.1 回溯法的基本思想
(1)解空间 设问题的解向量为X=(x1,x2,…,xn) ,xi的取值范 围为有穷集Si .把xi的所有可能取值组合,称 为问题的解空间.每一个组合是问题的一个可 能解.
5.1 回溯法的基本思想
(1)解空间 例:0/1背包问题,S={0,1},当n=3时,0/1背 包问题的解空间是: {(0,0,0),(0,0,1),(0,1,0),(0,1,1),(1,0,0),(1,0,1),(1, 1,0),(1,1,1)} 当输入规模为n时,有2n种可能的解.
5.1 回溯法的基本思想
(3)状态空间树的动态搜索
状态空间树的动态搜索 l_结点(活结点):所搜索到的结点不是叶结点,且满足 约束条件和目标函数的界,其儿子结点还未全部搜索完毕, e_结点(扩展结点):正在搜索其儿子结点的结点,它也 是一个l_结点; d_结点(死结点):不满足约束条件,目标函数,或其儿 子结点已全部搜索完毕的结点,或者叶结点.以d_结点作 为根的子树,可以在搜索过程中删除.
皇问题) (8-皇问题) 皇问题
8皇后问题可以表示成8-元组(x1,…,x8),其中xi是放在第 i行的皇后所在的列号.于是,解空间由88个8-元组组 成. 约束条件:xi≠xj for all i, j |xi-xj|≠| j-i | 约束条件之一为没有两个xi相同(即任意两个皇后不在 同一列上).将其加入到元组的定义中,这时解空间的 大小由88个元组减少到8!个元组.
n后问题算法的描述如下:
int n, sum,x[]; void n_queens(){
sum=0; x[ ]=0; backtrack(1); }
void backtrack(int t) {
if (t>n){sum++;output(x)} else for(i=1;i<=n;i++){ x[t]=i; if place(x,t) backtrack(t+1); }
5.2 回溯法的算法框架
递归回溯的一般解法:
– –
VoБайду номын сангаасd traceback(int t) {
If(t>n) output(x); Else for(i=f(n,t);i<=g(n,t);i++){ x[t]=h[i]; if(constraint(t)&&bound(t)) backtrack(t+1); }


}
5.3 回溯法的应用 回溯法的应用—n后问题 后问题
例1(8-皇问题)
皇问题) 例1(8-皇问题) ( 皇问题
在8×8的棋盘上放置8个皇后,使得这8个皇 后不在同一行,同一列及同一斜角线上.如下 1 2 3 4 5 6 7 8 图6.1: Q
1 2 3 4 5 6 7 8
Q Q Q Q Q Q Q
int c,n,w[],p[],cw,cp,bestp; void backtrack(int i){ if(i>n){bestp=cp; return;} if(cw+w[i]<=c){ cw+=w[i]; cp+=p[i]; backtrack(i+1); cw-=w[i]; cp-=p[i]; } if(bound(i+1)>bestp) backtrack(i+1); } int bound( int i){ int cleft=c-cw; int bound=cp; while(i<=n&&w[i]<=cleft){ cleft-=w[i]; bound+=p[i]; i++; } if(i<=n) bound+=pi]/w[i]*cleft; return bound; }
5.1 回溯法的基本思想
(1)解空间 例:货郎担(旅行商)问题, S={1,2,…,n},当 n=3时, S={1,2,3} ,货郎担问题的解空间是: {(1,1,1),(1,1,2),(1,1,3),(1,2,1),(1,2,2),(1,2,3),┅ ,(3,3,1),(3,3,2),(3,3,3)} 当输入规模为n时,它有nn种可能的解. 考虑到约束方程xi≠xj.因此,货郎担问题的解 空间压缩为: {(1,2,3),(1,3,2),(2,1,3),(2,3,1),(3,1,2),(3,2,1)} 当输入规模为n时,它有n!种可能的解.
相关文档
最新文档