简单回溯法教案
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
优化(算法2)
• 显然一定有面值为1的邮票。可以按递增的次序来搜索各种邮票的面值, 关键在于确定每一层搜索的上界。设当前搜索到第m层,用不超过N-1 张前m-1种邮票可以得到的MAX值记为MAX(m-1),则第m种邮票面值 的上界是MAX(m-1)+1,否则邮资值MAX(m-1)+1就无法用这m种邮票 贴出来了。 • Procedure Search(m) 搜索第m种邮票的面值 • 1. If m = K+1 Then [ • 2. If 当前方案更优 Then 保存当前方案; • 3. Exit; • 4. ] • 5. For I Am-1+1 to Max(M-1) do [ • 6. Am := I; • 7. Search(m+1); • 8. ]
邮票问题
设有已知面额的邮票M种,
邮票面值设计
• 给定一个信封,最多只允许粘贴N张邮票,计算在给定K(N+k<=40) 种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面 值,能得到最大max ,使得1-max之间的每一个邮资值都能得到。 • 例如,N=3,K=2,如果面值分别为1分、4分,则在l分-6分之间的每 一个邮资值都能得到(当然还有8分、9分和12分):如果面值分别为 1分、3分,则在1分-7分之间的每一个邮资值都能得到。可以验证当 N=3,K=2时,7分就是可以得到连续的邮资最大值,所以MAX=7,面 值分别为l分、3分。 • 样例: • INPUT • N=3 k=2 • OUTPUT • 1 3 • MAX=7
var n,p:integer;{字串长度和可选字母的个数} tl:longint; ed:char; s:sБайду номын сангаасring; { 满足条件的字串数} { 可选字母集中的最大字母} {满足条件的字串}
构造字串
procedure solve(at:integer);{递归扩展第at if i>at div 2 then solve(at+1);{若当前 个字母} 字串符合条件,则递归扩展下一个字母} var ch:char; i:integer; begin 串} end{for}
N皇后问题
在N*N的棋盘上放置N个皇后而彼此不受攻击 (即在棋盘的任一行,任一列和任一对角 线上不能放置2个皇后),编程求解所有的 摆放方法。
八皇后的两组解
基本思想
• 由于皇后的摆放位置不能通过某种公式来 确定,因此对于每个皇后的摆放位置都要 进行试探和纠正,这就是“回溯”的思想。 • 在N个皇后未放置完成前,摆放第i个皇后和 第i+1个皇后的试探方法是相同的,因此完 全可以采用递归的方法来处理。
算法基本框架
• • • • • • • • • • • • • • Procedure Try(I:integer); {搜索第I行皇后的位置} var j:integer; begin if I=n+1 then 输出方案; for j:=1 to n do if 皇后能放在第I行第J列的位置 then begin 放置第I个皇后;
基本算法
搜索的过程实质上是枚举K种邮票的面值,然后计算这K种邮票对应的 MAX值。于是可以得到如下算法: 算法1 算法 • Procedure Search(m) 搜索第m种邮票的面值 • 1. If m = K+1 Then [ • 2. If 当前方案更优 Then 保存当前方案; • 3. Exit; • 4. ] • 5. For I Am-1+1 to N*Am-1+1 do [ • {N*Am-1+1肯定不能有前K中邮票构成} • 6. Am := I; • 7. Search(m+1); • 8. ]
0,1背包问题
• 已知一个容量大小为M重量的背包和N种物 品,每种物品的重量为Wi。若将物品放入 背包将得到Pi的效益,求怎样选取物品将得 到效益最大
算法分析
• 蓝皮书《数据结构与算法》179页
算法分析
• 本题可以用递归求解:设当前有N个物品,容量为M;因 为这些物品要么选,要么不选,我们假设选的第一个物品 编号为I(1~I-1号物品不选),问题又可以转化为有N-I个 物品(即第I+1~N号物品),容量为M-Wi的子问题…… 如此反复下去,然后在所有可行解中选一个效益最大的便 可。 • 另外,为了优化程序,我们定义一个函数如下: • F[I]表示选第I~N个物品能得到的总效益。不难推出: • F[N]=Pn • F[I]=F[I+1]+Pi (I=1…N-1) • 假设当前已选到第I号物品,如果当前搜索的效益值 +F[I+1]的值仍然比当前的最优值小,则没有必要继续搜 索下去。
算法框架
• • • • • • • • • • • • • • • • • Procedure Search(I:Integer; J:Byte); {递归求解} Var K :Byte; Begin If Now+F[J]<=Ans Then Exit; {如果没有必要搜索下去} If Now>Ans Then Begin {修改最优解} Ans:=Now; Out:=Ou; End; For K:=J To N Do {选取物品} If W[K]<=I Then Begin Now:=Now+P[K]; Ou[K]:=True; Search(I-W[K],K+1); Now:=Now-P[K]; Ou[K]:=False; End; End;
简单回溯法教案简单回溯法?邮票问题?n皇后问题?背包问题?寻找国都名?构造字串回溯法回溯法也是搜索算法中的一种控制策略但与枚举法不同的是它是从初始状态出发运用题目给出的条件规则按照深度优秀搜索的顺序扩展所有可能情况从中找出满足题意要求的解答
简单回溯法教案
简单回溯法
• • • • • 邮票问题 N皇后问题 背包问题 寻找国都名 构造字串
搜索的方向
• 要求从这个矩阵中找出这些国都名, 并输出它们的起始位置及方向。
算法思想
• 将字符矩阵读入到二维数组,然后对每一个国都名进行搜 索,首先需要在矩阵中找到国都名的第一个字符,然后沿 八个方向进行搜索。直到找到国都名为止。若在矩阵中没 有找到,则输出相应的信息。 • 在搜索过程时,类似八皇后问题,建立一个标志数组,标 识已经搜索过的方向,在对八个方向搜索时,可以建立一 个方向数组,使得程序更加简洁明了 • Const Fx : Array[1..8,1..2] Of Shortint {定义八个方向} =((0,1),(0,-1),(1,0),(-1,0),(1,-1),(-1,1),(1,1),(-1,-1));
• • • • • • • • • • • • • • • • • • •
Procedure Work(T,X,Y:Integer); {搜索路径,T为国都名的字符位置,X,Y为当前搜索的坐标} Var I : Integer; Begin If T=Length(S)+1 Then begin {搜索完,打印输出} Out; exit end; For I:=1 To 8 Do {八个方向进行搜索} Begin X:=X+Fx[I,1]; Y:=Y+Fx[I,2]; {坐标变化} If (A[X,Y]=S[T])And(B[X,Y]) Then Begin W:=W+Chr(I+48); {记录路径} B[X,Y]:=False; {设置已经搜索} Work(T+1,X,Y); {继续搜索下一个} Delete(W,Length(W),1);{恢复原路径} B[X,Y]:=True; {恢复标志} End; X:=X-Fx[I,1]; Y:=Y-Fx[I,2]; {返回后,坐标恢复} End; End;
寻找国都名
• 给出一个矩阵及一些国都名:
o k d u b A l p g o r a s m u o s l o n yiblglrc krzurich oaibxmuz tpqglamv l c s d I e m o n v b n bonn paris oslo lima dublin tokyo london rome
end;{solve}
delete(s,length(s),1){恢复填前的字
if at=n+1 {若产生了一个满足条件的字串, begin 则输出,满足条件的字串数+1} readln(n,p);{输入字串长度和前缀长 then begin 短} writeln(f,s); inc(tl);exit{回溯} ed←chr(ord('a')+p-1);{计算可选字母 end;{then} 集中的最大字母} for ch←'a' to ed do begin s←s+ch;i←1;{检查当前字串是否符合条件} {搜索每一个可填字母} s←''; tl←0;{满足条件的字串初始化 为空,字串数为0} solve(1);{从第1个字母开始递归计算所 有满足条件的字串}
生成长度为n的字串,其字符从26个英文字母的前p(p≤26)个字母中选取, 26个英文字母的前p(p≤26 生成长度为n的字串,其字符从26个英文字母的前p(p≤26)个字母中选取,使得 没有相邻的子序列相等。例如p= n=5 p=3 没有相邻的子序列相等。例如p=3,n=5时 a’满足条件 ‘a b c b a’满足条件 c’不满足条件 ‘a b c b c’不满足条件 输入: 输入:n,p 分析 输出: 输出:所有满足条件的字串 状态: 状态 : 待扩展的字母序号at。实际上字串s亦参与了递归运算,但是由于该 变量的存储量太大,因此我们将s设为全局变量; 边界条件和目标状态:产生了一个满足条件的字串,即at=n+1; 边界条件和目标状态: 搜索范围: 搜索范围:第at位置可填的字母集{'a'.. chr(ord('a')+p-1)}; 约束条件: 约束条件:当前字串没有相邻子串相等的情况
对放置皇后的位置进行标记; Try(I+1) 对放置皇后的位置释放标记;
end; end;
细节处理
• 怎样判断某列放置了皇后 A:array [1..MaxN] of Boolean; {竖线被控制标记} • 怎样判断某对角线上放置了皇后 B:array [2..MaxN * 2] of Boolean; {左上到右下斜线被控制标记} C:array [1–MaxN..MaxN–1] of Boolean; {左下到右上斜线被控制标记}
回溯法
回溯法也是搜索算法中的一种控制策略,但与枚举法不同的是,它是从初始状态出 发,运用题目给出的条件、规则,按照深度优秀搜索的顺序扩展所有可能情况,从 中找出满足题意要求的解答。回溯法是求解特殊型计数题或较复杂的枚举题中使用 频率最高的一种算法。
procedure run(当前状态); var i:integer; begin if 当前状态为边界 then begin if 当前状态为最佳目标状态 then 记下最优结果;exit;{回溯} end;{then} for i←算符最小值 to 算符最大值 do begin 算符i作用于当前状态,扩展出一个子状态; if (子状态满足约束条件) and (子状态满足最优性要求)then run(子状态); end;{for} end;{run} 我们在应用回溯法求所有路径的算法框架解题时,应考虑如下几个重要因素:
定义状态: ⑴定义状态:即如何描述问题求解过程中每一步的状况。为了精简程序, 增加可读性,我们一般将参与子结点扩展运算的变量组合成当前状态列入 值参,以便回溯时能恢复递归前的状态,重新计算下一条路径; 边界条件: ⑵边界条件:即在什么情况下程序不再递归下去。如果是求满足某个特定 条件的一条最佳路径,则当前状态到达边界时并非一定意味着此时就是最 佳目标状态。因此还须增加判别最优目标状态的条件; ⑶搜索范围:在当前状态不满足边界条件的情况下,应如何设计算符值的 搜索范围: 范围。换句话说,如何设定for语句中循环变量的初值和终值。 ⑷约束条件和最优性要求:当前扩展出一个子结点后应满足什么条件方可 约束条件和最优性要求: 约束条件和最优性要求 继续递归下去;如果是求满足某个特定条件的一条最佳路径,那么在扩展 出某个子状态后是否继续递归搜索下去,不仅取决于子状态是否满足约束 条件,而且还取决于子状态是否满足最优性要求。 参与递归运算的参数: ⑸参与递归运算的参数:将参与递归运算的参数设为递归子程序的值参或 局部变量。若这些参数的存储量大(例如数组)且初始值需由主程序传入, 为避免内存溢出,则必须将其设为全局变量,且回溯前需恢复其递归前的 值。