回溯算法

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

f[i] := TRUE dfs(g + 1) f[i] := FALSE;
f[1] := TRUE dfs( 2) f[1] := FALSE; f[2] := TRUE dfs(3) f[2] := FALSE; f[3] := TRUE dfs(4) f[3] := FALSE;
例2:n皇后问题 在n×n的国际象棋棋盘上,放置n个 皇后,使任何一个皇后都不能吃掉另一个, 需满足的条件是:同一行、同一列、同一 对角线上只能有一个皇后。求所有满足要 求的放置方案。
主要代码: procedure search(dep:longint); var i:longint; begin if dep>n then print else for i:=1 to n do begin a[dep]:=i; search(dep+1); end; end;
program pailie(input,output); var n:integer; a:array[1..20] of integer; procedure print; var i:integer; begin for i:=1 to n do write(a[i]); writeln; end;
回溯算法
——2016冬令营第4讲
1
迷宫游戏
入口 回溯
回溯 回溯
回溯
出口
搜索算法
对某些问题建立数学模型时,即使有一 定的数学模型,但采用数学方法解决有一定 的困难。对于这一类试题,我们用模拟或搜 索求解。 在缺乏解决问题的有效模型时,搜索却是一 种行之有效的解决问题的基本方法。 枚举法(穷举法) 深度优先搜索(回溯法) 广度优先搜索
procedure search(dep:longint); var i:longint; begin if dep>n then print else for i:=1 to 4 do{每个城市有四种颜色} begin a[dep]:=i; if check(dep) then search(dep+1); end; end;
进一步思考
全排列:输入n输出1..n个数的全部排列 (数字不重复) 1~3的全排列
123 132 213 231 312 321 6
Procedure dfs(g : Integer); { 递归过程 g 为当前深度 } Var i : Integer; Begin If (g > n)Then Begin For j := 1 To n Do { 输出一个排列方案 } Write(a[j], ' '); Writeln; { 每个方案 1 行 } Inc(tot); { 总数加 1, 等价于 tot := tot + 1; } End; For i := 1 To n Do { 枚举第 g 层应排的数 } If not f[i] Then { 如果 i 没有排列过 } Begin f[i] := TRUE; { 标志数组赋为已排列 } a[g] := i; { 第 g 层用 i} dfs(g + 1); { 继续枚举第g+1层} f[i] := FALSE; { 回溯,标志数组还原 } End; End;
代码实现: procedure try(dep:longint); var i:longint; begin if dep>n then print else for i:=1 to n do begin a[dep]:=i; try(dep+1); end; end;
过程print 为打印方案,打印方案前需要判断此方案是否有冲突
表示A,B相邻 Output
12
13 14 15 Sample Output
32
一个数表示染色方法数
324
分析: 我们一次从第一个城市开始染色,接着第二 ,第 三……每个城市有四种颜色可供选择,每次在染色的 时候只需考虑已经染好色的城市跟当前城市相邻且为 同一种颜色则不符合要求,否则就染好色并进入下一 个城市染色。 5个城市不考虑不符合要求的染色方案,所有染色方 案为 11111 11112 11113 ...... 55555 此题又可转换为全排形式。利用回溯来实现。
递归回溯 定义一个手工栈记录递归调用前及回溯时的断点; procedure Search(dep:integer); begin if 当前是目标状态 then 输出解或者做计数、评价处理 else for i:=1 to 状态的拓展可能数 do if 第i种状态拓展可行 then begin 保存现场(断点,维护参数表); Search(dep+1); 恢复现场(回溯,回到上一个断点继续执行); end; end;
29
var a:array[1..100]of integer; n,s:longint; procedure print; var i,j:longint; begin for i:=1 to n-1 do write(a[i],' '); writeln; end; function check(dep:integer):boolean; var i:longint; begin check:=true; for i:=1 to dep-1 do if (a[i]-a[dep]=i-dep)or(a[i]a[dep]=dep-i)or(a[i]=a[dep]) then begin check:=false;exit;end; 30 end;
刚才的方法为生成皇后的摆放方案再去判断是否符合 要求,效率比较低,我们能不能每摆放一个皇后就看 这个皇后摆放的位置对还是不对,这样可以节省很多 无效的搜索 procedure try(dep:longint); var i:longint; begin if dep>n then inc(total) else for i:=1 to n do begin a[dep]:=i; if pd(dep) then try(dep+1); end; end;
check为检查当前城市填的颜色是否可行
function check(dep:longint):boolean; var i:longint; begin check:=true; for i:=1 to dep-1 do if (map[dep,i]=1)and(a[dep]=a[i]) then check:= false; end;
11
思考3
输出 n个数字的刚才那种排列又该如何处理? 利用回溯思想实现 n重循环
12
例1:数字排列
问题描述: 输入n输出1..n个数的全部排列。数字可以重复。
样例输入 3
样例输出 111 112 113 121 122 123 131 132 133 .... 333
13
分析: 典型的用回溯来实现n重循环
例3:四色问题
在有一张包含N(N≤10)块区域的地图,给出M(M≤50) 个描述,每组描述A,B表示A,B相邻,相邻的区域不能染 同一种颜色,一种有四种颜色,请你用这四种颜色给地图染 色,一共有多少中染色方法?
Input 第一行两个数N和M
Sample Input 54
接下来M行,每行一组数A,B
思考1
想输出 111 112 113 121 122 123 131 132 133 211 212 213 221 222 223 231 232 233 311 312 313 321 322 323 331 332 333
10
思考2
输出 1111 1112 1113 1114 1121 1122 1123 1124 1131 1132 1133 1134 1141 1142 1143 1144 1211 1212 ...... 4444 又该如何输出?
end;
如果我们不考虑错误的方案数字,那么 摆放4皇后的所有方案就成为: 1111 1112 1113 1114 1121 1122 1123 ....4444 就转成了全排问题。 n皇后问题就转换为n个数字的全排, 只需把符合要求的方案挑选出来就行了, 那么此问题就可以转换为生成n个数字的 全排,我们可以利用回溯法来实现。
20
n皇后问题描述
0 1 2 3 0 1 2 3 0#次对角线 2#次对角线 4#次对角线 6#次对角线 1#次对角线 3#次对角线 5#次对角线



1#主对角线 3#主对角线 5#主对角线 0#主对角线 2#主对角线 4#主对角线 6#主对角线
在n×n格的棋盘上如何能摆上n个 皇后而使她们都不能互相吃!
5
迷宫游戏
入口
方向: 上 次序: 4
下 左 1 3
右 2
来自百度文库
2 3 -1
1 1 1 2 1 1 1 2 2 1 1 31 -12 1
出口
回溯法是搜索算法中的一种控制策略, 它是从初始状态出发,运用题目给出的条 件、规则,按照深度优先搜索的顺序扩展 所有可能情况,从中找出满足题意要求的 解答。回溯法是求解特殊型计数题或较复 杂的枚举题中使用频率最高的一种算法。
23
以4皇后为例:
24
function pd(i:longint):boolean;
var j:longint; begin pd:=true;
for j:=1 to i-1 do
if (a[i]=a[j])or (a[i]-a[j]=i-j)or (a[i]-a[j]=j-i)
then begin pd:=false; end;
3
回溯法的基本思想
为了求得问题的解,先选择某一种可能 情况向前探索,在探索过程中,一旦发 现原来的选择是错误的,就退回上一步 重新选择条件,继续向前探索,如此反 复进行,直至得到解或证明无解。
再看迷宫问题
深搜解迷宫时,通常用的是“穷举求解” 的方法,即从入口出发,顺某一方向向前探索, 若能走通,则继续往前走;否则沿原路退回, 换一个方向再继续探索,直至所有可能的通路 都探索到为止,如果所有可能的通路都试探过, 还是不能走到终点,那就说明该迷宫不存在从 起点到终点的通道。
DFS算法框架1——直接递归 procedure Search(dep:integer,参数表); //需要时还可以自定义一些参数; begin if 当前是目标状态 then 输出解或者做计数、评价处理 else for i:=1 to 状态的拓展可能数 do if 第i种状态拓展可行 then begin //维护自定义参数; Search(dep+1,参数表); end; end;
procedure search(dep:integer); var i:longint; begin if dep>n then print else for i:=1 to n do begin a[dep]:=i; if check(dep) then search(dep+1); end; end; end; begin readln(n); search(1) end.
3.1.3 回溯法解决n皇后问题

















【分析】
一、问题解的形式: a:array [1..n] of integer; a[i]:第a[i]列,保证所有皇后不同行(第i个皇后 放在第i行) 问题的解变成求(a[1],a[2],…,a[n]) 4皇后问题的解: (2,4,1,3), (3,1,4,2)
pd为判断第dep 个皇后放在i的位置是否合适,如果合适再摆 放后一个皇后如果不合适,则第dep个皇后选择另一个方案。
二、如何判断第dep行的皇后能不能放在第i列:
function pd(i:longint):boolean; var j:longint; begin pd:=true; for j:=1 to i-1 do if (a[i]=a[j])or (a[i]-a[j]=i-j)or (a[i]-a[j]=j-i) then begin pd:=false; end; end;
procedure search(dep:longint); var i:longint; begin if dep>n then print else for i:=1 to n do begin a[dep]:=i; search(dep+1); end; end; begin readln(n); search(1); end.
相关文档
最新文档