- 15
- 0
- 约9.59千字
- 约 10页
- 2017-02-01 发布于北京
- 举报
回溯算法入门及应用
广东省东莞市东华高级中学 杨光文 难易指数:★★★
在求解一些问题(如马的遍历、选书、八皇后问题、自然数的拆分等问题)时,题目的要求可能是求出原问题的一种或所有可能的解决方案。这类问题的解往往是由一个一个的步骤或状态所构成的,每一步骤又有若干种可能的决策方案;由于没有固定、明确的数学解析方法,往往要采用搜索的做法,即从某一个初始状态出发,不断地向前(即下一个状态)搜索,以期最终达到目标状态,从而得到原问题的一个解或所有的解。在搜索的过程中,由于问题本身及所采取的搜索方法的特点(如在缺乏全局及足够的前瞻信息的情况下进行搜索等),会导致走到某一状态就走不下去的情况,这时,就必须回头(即回到上一步,而不是回到最初的状态),再尝试其他的可能性,换一个方向或方法再试试。这样,不断地向前探索、回溯,再向前、再回溯,直至最终得出问题的解,或者一路回溯到出发点(出现这种情况即表示原问题无解)。注意,这种搜索过程并不是尝试搜索问题解空间中所有的可能状态和路径,而是采用深度优先的方式,沿着一条路径,尽可能深入地向前探索,这就是回溯算法。
一、回溯算法的定义:
回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。用回溯算法解决问题的一般步骤为:
1、定义一个解空间,它包含问题的解。
2、利用适于搜索的方法组织解空间。
3、利用深度优先法搜索解空间。
4、利用限界函数避免移动到不可能产生解的子空间。
问题的解空间通常是在搜索问题的解的过程中动态产生的,这是回溯算法的一个重要特性。
下面通过一个具体实例加深大家对回溯算法的认识。
二、回溯算法的应用举例:
例1:马的遍历
中国象棋半张棋盘如图1(a)所示。马自左下角往向右上角跳。规定只许往右跳,不许往左跳,马只能走日字。找出所有路径。
如图1(b),马最多有四个方向,若原来的横坐标为j、纵坐标为i,则四个方向的移动可表示为:
1: (i,j)→(i+2,j+1); (i3,j8)
2: (i,j)→(i+1,j+2); (i4,j7)
3: (i,j)→(i-1,j+2); (i0,j7)
4: (i,j)→(i-2,j+1); (i1,j8)
搜索策略:
S1:A[1]:=(0,0);
S2:从A[1]出发,按移动规则依次选定某个方向,如果达到的是(4,8)则转向S3,否则继续搜索下
一个到达的顶点;
S3:打印路径。
【算法设计】
procedure try(i:integer); {搜索}
var j:integer;
begin
for j:=1 to 4 do {试遍4个方向}
if 新坐标满足条件 then
begin
记录新坐标;
if 到达目的地 then print {统计方案,输出结果}
else try(i+1); {试探下一步}
退回到上一个坐标,即回溯;
end;
end;
【参考程序】
program exam1;
const x:array[1..4,1..2] of integer=((2,1),(1,2),(-1,2),(-2,1)); {四种移动规则}
var t:integer; {路径总数}
a:array[1..9,1..2] of integer; {路径}
procedure print(ii:integer); {打印}
var i:integer;
begin
inc(t);
for i:=1 to ii-1 do
write(a[i,1],,,a[i,2],-);
writeln(4,8,t:5);
end;
procedure try(i:integer); {搜索}
var j:integer;
begin
a[1,1]:=0;a[1,2]:=0;
for j:=1 to 4 do
if (a[i-1,1]+x[j,1]=0) and (a[i-1,1]+x[j,1]=4) and
(a[i-1,2]+x[j,2]=0) and (a[i-1,2]+x[j,2]=8) then
begin
a[i,1]:=a[i-1,1]+x[j,1];
a[i,2]:=a[i-1,2]+x[j,2];
if (a[i,1]=4) and (a[i,2]=8) then print(i)
else try(i+1); {搜索下一步}
a[i,1]:=0
原创力文档

文档评论(0)