⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 回溯算法.htm

📁 回溯法是一个既带有系统性又带有跳跃性的的搜索算法。本文档进行讲解。
💻 HTM
📖 第 1 页 / 共 2 页
字号:
            <TABLE cellSpacing=0 cellPadding=0 width=618>
              <TBODY>
              <TR>
                <TD width=616 colSpan=2>
                  <P align=right>&nbsp;</P></TD></TR>
              <TR>
                <TD width=181>
                  <P><IMG height=20 src="回溯算法.files/s2.gif" width=20 
                  align=absMiddle border=0> <B>回溯算法</B></P></TD>
                <TD width=433>
                  <P align=right><A 
                  href="http://www.muduhs.com/~yanxm/index1.htm">Index</A>&nbsp;&gt; 
                  <A href="http://www.muduhs.com/~yanxm/pds.htm">Alogri+Data 
                  str</A> &gt; <A 
                  href="http://www.muduhs.com/~yanxm/pds00.htm">常用算法</A> &gt; 
                  回溯</P></TD></TR>
              <TR>
                <TD width=616 background=回溯算法.files/bg.gif colSpan=2 
                height=1></TD></TR>
              <TR>
                <TD width=616 colSpan=2>
                  <P><BR>一、回溯法:<BR>回溯法是一个既带有系统性又带有跳跃性的的搜索算法。它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。否则,进入该子树,继续按深度优先的策略进行搜索。回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。而回溯法在用来求问题的任一解时,只要搜索到问题的一个解就可以结束。这种以深度优先的方式系统地搜索问题的解的算法称为回溯法,它适用于解一些组合数较大的问题。<BR><BR>二、算法框架:<BR>1、问题的解空间:应用回溯法解问题时,首先应明确定义问题的解空间。问题的解空间应到少包含问题的一个(最优)解。<BR><BR>2、回溯法的基本思想:确定了解空间的组织结构后,回溯法就从开始结点(根结点)出发,以深度优先的方式搜索整个解空间。这个开始结点就成为一个活结点,同时也成为当前的扩展结点。在当前的扩展结点处,搜索向纵深方向移至一个新结点。这个新结点就成为一个新的活结点,并成为当前扩展结点。如果在当前的扩展结点处不能再向纵深方向移动,则当前扩展结点就成为死结点。换句话说,这个结点不再是一个活结点。此时,应往回移动(回溯)至最近的一个活结点处,并使这个活结点成为当前的扩展结点。回溯法即以这种工作方式递归地在解空间中搜索,直至找到所要求的解或解空间中已没有活结点时为止。<BR>运用回溯法解题通常包含以下三个步骤:<BR>(1)针对所给问题,定义问题的解空间;<BR>(2)确定易于搜索的解空间结构;<BR>(3)以深度优先的方式搜索解空间,并且在搜索过程中用剪枝函数避免无效搜索;<BR><BR>3、递归回溯:由于回溯法是对解空间的深度优先搜索,因此在一般情况下可用递归函数来实现回溯法如下:<BR>procedure 
                  try(i:integer);<BR>var<BR>begin<BR>if i&gt;n then 输出结果<BR>else 
                  for j:=下界 to 上界 do<BR>begin<BR>x[i]:=h[j];<BR>if 
                  可行{满足限界函数和约束条件} then begin 置值;try(i+1); 
                  end;<BR>end;<BR>end;&nbsp;<BR><BR>说明:<BR>i是递归深度;&nbsp;<BR>n是深度控制,即解空间树的的高度;<BR>可行性判断有两方面的内容:不满约束条件则剪去相应子树;若限界函数越界,也剪去相应子树;两者均满足则进入下一层;<BR><BR>  搜索:全面访问所有可能的情况,分为两种:不考虑给定问题的特有性质,按事先顶好的顺序,依次运用规则,即盲目搜索的方法;另一种则考虑问题给定的特有性质,选用合适的规则,提高搜索的效率,即启发式的搜索。<BR>回溯即是较简单、较常用的搜索策略。<BR>基本思路:若已有满足约束条件的部分解,不妨设为(x1,x2,x3,……xi),I&lt;n,则添加x(i+1)属于s(i+2),检查(x1,x2,……,xi,x(i+1))是否满足条件,满足了就继续添加x(i+2)、s(i+2),若所有的x(i+1)属于s(i+1)都不能得到部分解,就去掉xi,回溯到(xi,x2,……x(i-1)),添加那些未考察过的x1属于s1,看其是否满足约束条件,为此反复进行,直至得到解或证明无解。&nbsp;<BR><BR>例子:<BR><BR> 例1、八皇后问题:要在国际象棋棋盘中放八个皇后,使任意两个皇后都不能互相吃。<BR>    
                  (提示:皇后能吃同一行、同一列、同一对角线的任意棋子。)<BR><BR>program tt;var a:array 
                  [1..8] of integer; b,c,d:array [-7..16] of integer; 
                  t,i,j,k:integer;procedure print;begin t:=t+1; write(t,' '); 
                  for k:=1 to 8 do write(a[k],' '); writeln;end;procedure 
                  try(i:integer);var j:integer;begin for j:=1 to 8 do 
                  {每个皇后都有8种可能位置} if (b[j]=0) and (c[i+j]=0) and (d[i-j]=0) then 
                  {判断位置是否冲突} begin a[i]:=j; {摆放皇后} b[j]:=1; {宣布占领第J行} c[i+j]:=1; 
                  {占领两个对角线} d[i-j]:=1; if i&lt;8 then try(i+1) 
                  {8个皇后没有摆完,递归摆放下一皇后} else print; {完成任务,打印结果} b[j]:=0; {回溯} 
                  c[i+j]:=0; d[i-j]:=0; end;end;begin for k:=-7 to 16 do {数据初始化} 
                  begin b[k]:=0; c[k]:=0; d[k]:=0; end; 
                  try(1);{从第1个皇后开始放置}end.  例2、跳马问题。在5*5格的棋盘上,有一个国家象棋的马,它可以朝8个方向跳,但不允许出界或跳到已跳过的格子上,要求在跳遍整个棋盘后再条回出发点。<BR><BR>program 
                  jump;<BR>  var<BR>   h:array[-1..7,-1..7] of integer;<BR>   
                  a,b:array[1..8] of integer;<BR>   i,j,num:integer;<BR>  
                  procedure print;<BR>   var i,j:integer;<BR>   begin<BR>    
                  num:=num+1;<BR>    if num&lt;=5 then<BR>    begin<BR>      for 
                  i:=1 to 5 do<BR>       begin<BR>        for j:=1 to 5 do 
                  write(h[i,j]:4);<BR>        writeln;<BR>       end;<BR>      
                  writeln;<BR>     end;<BR>   end;<BR>  procedure 
                  try(x,y,i:integer);<BR>   var  j,u,v:integer;<BR>   
                  begin<BR>    for j:=1 to 8 do<BR>     begin<BR>      
                  u:=x+a[j];<BR>      v:=y+b[j];<BR>      if h[u,v]=0 
                  then<BR>       begin h[u,v]:=i;<BR>        if i&lt;25 then 
                  try(u,v,i+1)<BR>        else print;<BR>        
                  h[u,v]:=0<BR>       end;<BR>     end;<BR>   end;<BR>  
                  begin<BR>   for i:=-1 to 7 do<BR>    for j:=-1 to 7 do<BR>     
                  if (i&gt;=1)and(i&lt;=5)and(j&gt;=1)and(j&lt;=5)<BR>      then 
                  h[i,j]:=0<BR>     else h[i,j]:=1;<BR>   a[1]:=2;b[1]:=1;<BR>   
                  a[2]:=1;b[2]:=2;<BR>   a[3]:=-1;b[3]:=2;<BR>    
                  a[4]:=-2;b[4]:=1;<BR>   a[5]:=-2;b[5]:=-1;<BR>   
                  a[6]:=-1;b[6]:=-2;<BR>   a[7]:=1;b[7]:=-2;<BR>   
                  a[8]:=2;b[8]:=-1;<BR>   num:=0;<BR>   h[1,1]:=1;<BR>   
                  try(1,1,2);<BR>   writeln('num=',num);<BR>  
                  end.<BR><BR>  例3:素数环: 
                  把从1到20这20个数摆成一个环,要求相邻的两个数的和是一个素数。<BR>〖问题分析〗 
                  非常明显,这是一道回溯的题目。从1开始,每个空位有20(19)种可能,只要填进去的数合法:<BR>与前面的数不相同;与左边相邻的数的和是一个素数。第20个数还要判断和第1个数的和是否素数。<BR><BR>〖算法流程〗<BR>1、数据初始化;<BR>2、递归填数:<BR>判断第J种可能是否合法;<BR>A、如果合法:填数;判断是否到达目标(20个已填完):是,打印结果;不是,递归填下一个;<BR>B、如果不合法:选择下一种可能;<BR><BR>参考程序:<BR><BR>program 
                  tt;<BR>var a:array [1..20] of 
                  integer;<BR>&nbsp;k:integer;<BR>function 
                  pd1(j,i:integer):boolean;<BR>begin<BR>&nbsp;pd1:=true;<BR>&nbsp;for 
                  k:=1 to i-1 do<BR>&nbsp;if a[k]=j<BR>&nbsp;then 
                  begin<BR>&nbsp;pd1:=false;<BR>exit;<BR>end;<BR>end;<BR>function 
                  pd2(x:integer):boolean;<BR>begin<BR>&nbsp;pd2:=true;<BR>&nbsp;for 
                  k:=2 to trunc(sqrt(x)) do<BR>&nbsp;if x mod k=0<BR>&nbsp;then 
                  begin<BR>&nbsp;pd2:=false;<BR>&nbsp;exit;<BR>end;<BR>end;<BR>function 
                  pd3(j,i:integer):boolean;<BR>begin<BR>&nbsp;if 
                  i&lt;20<BR>&nbsp;then pd3:=pd2(j+a[i-1])<BR>&nbsp;else 
                  pd3:=pd2(j+a[i-1]) and pd2(j+1);<BR>end;<BR>procedure 
                  print;<BR>begin<BR>&nbsp;for k:=1 to 20 
                  do<BR>&nbsp;write(a[k]:4);<BR>&nbsp;writeln;<BR>end;<BR>procedure 
                  try(i:integer);<BR>var j:integer;<BR>begin<BR>&nbsp;for j:=2 
                  to 20 do<BR>&nbsp;begin<BR>&nbsp;if pd1(j,i) and 
                  pd3(j,i)<BR>&nbsp;then begin<BR>&nbsp;a[i]:=j;<BR>&nbsp;if 
                  i=20<BR>&nbsp;then 
                  begin<BR>&nbsp;print;<BR>&nbsp;halt;<BR>end<BR>&nbsp;else 
                  try(i+1);<BR>&nbsp;a[i]:=0;<BR>&nbsp;end;<BR>&nbsp;end;<BR>end;<BR>begin<BR>&nbsp;for 
                  k:=1 to 20 
                  do<BR>&nbsp;a[k]:=0;<BR>&nbsp;a[1]:=1;<BR>&nbsp;try(2);<BR>end.&nbsp;<BR><BR>练习:<BR>   
                  1、对于任意一个m*n的矩阵, 
                  求L形骨牌覆盖后所剩方格数最少的一个方案.<BR>  2、任何一个正整数都可以用2的幂次方表示.<BR>    例如:137=2^7+2^3+2^0<BR>    同时约定次方用括号来表示,即a^b可表示为a(b)<BR>    由此可知,137可表示为:2(7)+2(3)+2(0)<BR>    进一步:7=2^2+2+2^0 
                  (2^1用2表示)<BR>    3=2+2^0<BR>    所以最后137可表示为:2(2(2)+2+2(0))+2(2+2(0))+2(0)<BR>    又如:1315=2^10+2^8+2^5+2+1<BR>    所以1315最后可表示为:2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)<BR>    输入:正整数(n&lt;=20000)<BR>    输出:符合约定的n的0,2表示(在表示中不能有空格)&nbsp;<BR><BR>习题:<BR>1、0-1背包:n=3,w=[16,15,15],p=[45,25,25],c=30<BR><BR>2、旅行售货员问题:某售货员要到若干城市去推销商品,已知各城市之间的路程(或旅费)。他要选定一条从驻地出发,经过每个城市一遍,最后回到驻地的路线,使总的路程(或总旅费)最小。<BR><BR>3、括号检验<BR>题目描述:输入一个代数表达式(只含有+,-,*,/,(,),1,2,3,4,5,6,7,8,9,0等字符,每个数字均小于10),设表达式除括号匹配有误外无其他错误.编程对输入的表达式检验,判断括号匹配是否正确.<BR><BR>正确的:<BR>1+2+4<BR>(1+2)+4<BR>(1+2) 
                  错误的:<BR>(1+)2<BR>(1+2(4+3))<BR>(1+2+3*(4+5()))<BR>1+2+3*(4+5))&nbsp;<BR><BR>4、四色问题:<BR>〖问题描述〗<BR>设有如下图所示的地图,每个区域代表一个省,区域中的数字代表省的编号,将每个省涂上红(R),蓝(B),白(W),黄(Y)四种颜色之一,使相邻的省份有不同的颜色。<BR><BR>1 
                  2 3 4&nbsp;<BR>5 
                  6&nbsp;<BR><BR>输入:用邻接矩阵表示地图。从文件中读入,文件格式如下:<BR>N 
                  (有N个省)<BR>N行用空格隔开的0/1串 
              (1表示相邻,0表示不相邻)<BR><BR>输出:RBWY串</P></TD></TR></TBODY></TABLE></TD>
          <TD width=152>&nbsp;</TD></TR></TBODY></TABLE></TD></TR>
  <TR>
    <TD vAlign=bottom height=81>  
      <TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
        <TBODY>
        <TR bgColor=#cccccc>
          <TD width=800 height=1><IMG height=1 width=800></TD>
          <TD width=459 height=1></TD></TR>
        <TR vAlign=top>
          <TD width=800>
            <TABLE cellSpacing=0 cellPadding=0 width=800>
              <TBODY>
              <TR>
                <TD width=210 height=10></TD>
                <TD width=590 colSpan=2 height=10></TD></TR>
              <TR>
                <TD width=210 height=14>
                  <P align=center><A onfocus=this.blur() 
                  href="http://www.muduhs.com/" target=_blank><FONT face=Verdana 
                  color=#999999 size=1>GO Muduhs WebSite!</FONT></A> </P></TD>
                <TD width=536 height=14>
                  <P><FONT face=Verdana size=1>Copyright &#9426;&nbsp; MuDu - Internet 
                  HighSchool. Some right reserved.</FONT></P></TD>
                <TD width=54 height=14>
                  <P align=right><A onfocus=this.blur() 
                  href="http://www.muduhs.com/~yanxm/pds05.htm#"><FONT 
                  face=Verdana size=1><B>-TOP</B></FONT></A> </P></TD></TR>
              <TR>
                <TD width=210 height=10></TD>
                <TD width=590 colSpan=2 height=10></TD></TR></TBODY></TABLE></TD>
          <TD width=459></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><MAP 
name=ImageMap1><AREA shape=RECT coords=81,1,161,33 
  href="http://www.muduhs.com/~yanxm/pds.htm"><AREA shape=RECT 
  coords=161,1,240,33 href="http://www.muduhs.com/~yanxm/contest.htm"><AREA 
  shape=RECT coords=240,1,320,34 
  href="http://www.muduhs.com/~yanxm/circle.htm"><AREA shape=RECT 
  coords=319,1,401,35 href="http://www.muduhs.com/~yanxm/gellery.htm"><AREA 
  shape=RECT coords=401,2,479,35 
  href="http://www.muduhs.com/~yanxm/board.htm"><AREA shape=RECT 
  coords=1,1,82,33 
href="http://www.muduhs.com/~yanxm/about.htm"></MAP></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -