回溯法

回溯法是一种技术,有点像分割-合并方法。一般而言,回溯法在优化问题中很有用,可以很快的找到有效解。

对于回溯法的抽象,我们可以将问题的解定义成一个n元组(x1,x2,…xn),其中每个xi都是有限集Si中的元素。因此,抽象的回溯问题,我们可以定义如下:

1.      找到一个向量,能够使目标函数P(x1,x2,…,xn)达到最优。

2.      找到一个向量,能够满足一个特定标准函数P(x1,x2,…,xn)的向量。

在回溯问题中,比较难的就是找到约束函数,约束函数可以是显式的,也可以是隐式的。

1.      显式约束:比如说,每个元素的约束值;

2.      隐式约束:像是内部约束。

 

比较典型的回溯问题,如8皇后问题,问题的具体描述这里就不再赘述。

1.      一个8x8的表格,解集可以定义为一个8元组(x1,x2,…,x8),比如,一个正确的解是(4,6,8,2,7,1,3,5)

2.      显式约束像是xi Î Si,Si={1,2,3,4,5,6,7,8}, 1≤ i≤ 8,隐示约束像是任意两个不能在同一行或是同一列或同一斜线。

 

通过总结,我们可以建立一个状态空间树,进而通过DFS搜索来找到一个可行解,但是暴力式的搜索不是办法,可以使用回溯。

状态空间树中的术语:问题状态,状态空间,状态空间树,解状态,答案状态,

状态树中的搜索:alivenode, E-node , dead-node

在遍历过程中,回溯法不同于暴力法的是,在每个E-node中通过使用约束来杀死alive node,这样就不用再往下接着查找。

 

回溯算法伪代码如下所示:

BACKTRACKING(n)

  kß1;

  while k>0 do

    if there are uncheckedX(k), X(k)∈T(X(1),…,X(k-1)) and B(X(1),…,X(k))=true

          then   if (X(1),…,X(k) is an answer)

                           then  print (X(1),…,X(k))

                 if (k < n)

                              kßk+1

                        else

                                        kßk-1

约束解是X(1:n),一旦确认为可行解,就将其打印出来。

T(X(1),…,X(k-1)):已知X(1),…,X(k-1).后,返回所有可能的X(k)

B(X(1),…,X(k)):返回X(1),…,X(k-1).是否满足隐示约束。

 

 

 

 

 

 

 

 

n-Queen问题的回溯算法如下所示:

NQUEENS(n)

      X(1)ß0;kß1

      while k>0 do

              X(k)ßX(k)+1

              while X(k) ≤ nand not PLACE(k) do

                    X(k)ßX(k)+1

              if X(k) ≤ n

                    then   if k=n

                                       thenprint (X)

                           else kßk+1;X(k)ß0

              elsekßk-1;

PLACE(k)

    iß1

    while i<k do

            if X(i)=X(k) or|X(i)-X(k)| = |i-k|

                    thenreturn false

            ißi+1

    return true

 

 

 

 

第二个经典问题,subset-sum问题

问题描述如下:

Given n+1 positive integers: wi , 1≤i≤n,and M , Find all the subsets of W={wi} , of which thesummary equals to M.

–  E.g. n=4, (wl,w2,w3,w4)=(11,13,24,7),M=31

»     The expected subsets are (11,13,7) and (24,7).

The form of solution

–  A solution of subset-sumproblem is defined as an n-tuple        (x1,x2,… ,xn), where xiÎ{0,1}, 1≤i≤n.If wi is included in the subset, then xi=1, otherwisexi=0.

»     The above answers can bedefined as (1,1,0,1)and (0,0,1,1)。

 

 

在这里,引入了递归的回溯方法。递归回溯的伪代码如下所示,其中,W(i)已经按大小顺序做了排序。

RECURSIVE-BACKTRACKING( k )

    for each X(k), X(k)∈T(X(1),…,X(k-1)) andB(X(1),…,X(k))=true do

               if (X(1),…,X(k)is an answer)

                           then  print (X(1),…,X(k))

               if (k<n)

                           then call RECURSIVE-BACKTRACKING( k+1 )

 

针对该问题,递归回溯算法的伪代码如下所示:

ORIGINAL-SUMOFSUB(k)

   X(k)ß1

   if

        then  print(X(j),jß1 tok)

        else   if

                      thencall SUMOFSUB(k+1)

   X(k)ß0

   if

         then callSUMOFSUB(k+1)

 

 

 

 

SUMOFSUB(s,k,r)

   X(k)ß1

   if s+W(k)=M

        then  print(X(j),jß1 tok)

        else   if s+W(k)+W(k+1) ≤ M

                      thencall SUMOFSUB(s+W(k),k+1,r-W(k))

   if s+r-W(k) ≥ M ands+W(k+1) ≤ M

         then   X(k)ß0

                   callSUMOFSUB(s,k+1,r-W(k))

 

 

那为什么n-queen问题和subsum问题,一个是非递归,而另一个是递归呢。

 

 

第三个比较经典的的例子就是0-1背包问题,对于0-1背包问题,难点在于不是找到可行解,而且还要找到最优解。这样,问题的关键就是如何找到约束函数。

约束函数的主要作用就是杀掉alive-node。

 

 

 

 

 

 

 

 

 

 

 

BOUND( p,w,k,M )

    bßp; cßw

    for ißk+1 to n do

        cßc+W(i)

        if c<M then bßb+P(i)

            else return(b+(1-(c-M)/W(i))*P(i))

   return (b)

 

 

BKNAP1( M,n,W,P,fw,fp,X )

    cwßcpß0;kß1;fpß-1

    loop

        while k≤ n and cw+W(k)≤ M do

                   cwßcw+W(k);cpßcp+P(k);Y(k)ß1;kßk+1

        if k>n then fpßcp;fwßcw;kßn;XßY

                   else Y(k)ß0

        while BOUND(cp,cw,k,M)≤ fp do

                   while k¹0 andY(k)¹1 do

                         kßk-1

                   if k=0 thenreturn

                   Y(k)ß0;cwßcw-W(k);cpßcp-P(k)

       kßk+1

 

 

BOUND函数用于判定当前按照贪婪方法将背包装满(假设可以装物品的一部分),在BKNAP1函数中,如果当前alive-node节点的BOUND函数不如之前的叶子结点的最终fp,那么,我们就可以将这个alive-node杀掉。这也算是对回溯算法的约束函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值