回溯,计算机算法,回溯法也称试探法,它的基本思想是:从问题的某一种状态(初始状态)出发,搜索从这种状态出发所能达到的所有“状态”,当一条路走到“尽头”的时候(不能再前进),再后退一步或若干步,从另一种可能“状态”出发,继续搜索,直到所有的“路径”(状态)都试探过。这种不断“前进”、不断“回溯”寻找解的方法,就称作“回溯法”。
步骤
用回溯算法解决问题的一般步骤为:
一、定义一个解空间,它包含问题的解。
二、利用适于搜索的方法组织解空间。
三、利用深度优先法搜索解空间。
四、利用限界函数避免移动到不可能产生解的子空间。问题的解空间通常是在搜索问题的解的过程中动态产生的,这是回溯算法的一个重要特性。
回溯法是一个既带有系统性又带有跳跃性的的搜索算法。它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。否则,进入该子树,继续按深度优先的策略进行搜索。回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。而回溯法在用来求问题的任一解时,只要搜索到问题的一个解就可以结束。这种以深度优先的方式系统地搜索问题的解的算法称为回溯法,它适用于解一些组合数较大的问题.
递归回溯
递归回溯:由于回溯法是对解空间的
深度优先搜索,因此在一般情况下可用
递归函数来实现回溯法如下:
procedure try(i:integer);
var
begin
if i>n then 输出结果
begin
x:=h[j];
if 可行{满足限界函数和约束条件} then begin 置值;try(i+1); end;
end;
end;
说明:
i是递归深度;
n是深度控制,即解空间树的的高度;
可行性判断有两方面的内容:不满约束条件则剪去相应子树;若限界函数越界,也剪去相应子树;两者均满足则进入下一层;
搜索:全面访问所有可能的情况,分为两种:不考虑给定问题的特有性质,按事先顶好的顺序,依次运用规则,即盲目搜索的方法;另一种则考虑问题给定的特有性质,选用合适的规则,提高搜索的效率,即启发式的搜索。
回溯即是较简单、较常用的搜索策略。
基本思路:若已有满足约束条件的部分解,不妨设为(x1,x2,x3,……xi),I
回溯设计
1.用栈保存好前进中的某些状态.
2.制定好约束条件
【例1】从1到X这X个数字中选出N个,排成一列,相邻两数不能相同,求所有可能的排法。每个数可以选用零次、一次或多次。例如,当N=3、X=3时,排法有12种:121、123、131、132、212、213、231、232、312、313、321、323。
由以上过程可以看出,回溯法的思路是:问题的每个解都包含N部分,先给出第一部分,再给出第二部分,……直到给出第N部分,这样就得到了一个解。若尝试到某一步时发现已经无法继续,就返回到前一步,修改已经求出的上一部分,然后再继续向后求解。这样,直到回溯到第一步,并且已经将第一步的所有可能情况都尝试过之后,即可得出问题的全部解。
程序
program p11_14;
const n=3;x=3;
var a:array [1..n] of 0..x;
p,c,I:integer;
begin
writeln;
p:=1; {从第一位开始}
c:=1; {从1开始选数字}
repeat
repeat
if (p=1) or (c<>a[p-1]) then {第一位可填任意数}
begin
a[p]:=c; {将数字C填到第P位上}
if p=n then {若已填到最后一位,则表明已求出了一个解}
begin
for I:=1 to n do write(a); {显示这个解}
writeln;
end;
P:=P+1; {继续下一位}
C:=1; {下一位从1开始}
End
Else
C:=c+1; {下一位仍然从1开始选数字}
Until (p>n) or (c>X); {直到已填完最末位,或本位再无数字可选}
Repeat
P:=p-1; {向前回溯}
Until (p=0) or (a)[p]
If p>0 then {若非首位,则将该位变为下一个可取的数字}
C:=a[P]+1;
Until p=0; {将第一位回溯完毕后,程序结束}
End.
由键盘上输入任意n个符号,输出它的
全排列。(一个符号只能出现一次)
program hh;
const n=3;
var i,k:integer;
x:array[1..n] of integer;
st:string[n];
t:string[n];
procedure input;
var i:integer;
begin
write('Enter string=');readln(st);t:=st;
end;
function place(k:integer):boolean;
var i:integer;
begin
place:=true;
for i:=1 to k-1 do
if x=x[k] then begin place:=false; break end;
end;
procedure print;
var i:integer;
begin
for i:=1 to n do write(t[x]);writeln;
end;
begin
input;
k:=1;x[k]:=0;
while k>0 do
begin
x[k]:=x[k]+1;
while (x[k]<=n) and (not place(k)) do x[k]:=x[k]+1;
if x[k]>n then k:=k-1
else if k=n then print
else begin k:=k+1;x[k]:=0
end
end ;
readln
end.
运用
在编译原理中
如图2,在发生虚假匹配时需要进行回溯,就是退回到开始的位置