[算法分析]回溯法


回溯法:以深度優先方式系統搜索問題的解

  • 在問題的解空間樹中,按深度優先策略,從根節點出發搜索解空間樹

    • 當搜索到解空間樹的任一結點時,判斷該結點是否包含問題的解
      • 如果確定不包含,則跳過對以該結點為根的子樹的搜索,逐層向其祖先結點回溯;(剪枝)
      • 否則,進入該子樹,繼續深度優先搜索;
  • 求解問題的性質

    • 求問題的所有解時,要回溯到根,且根節點的所有子樹都被搜索后才結束
    • 求問題的一個解時,只要搜索到問題的一個解即可

回溯法的算法框架

問題的解空間

  • 定義:問題的解空間至少應包含問題的一個最優解
  • 組織:通常組織為樹或圖的形式——有利於回溯法對整個解空間的搜索

回溯法的基本思想

  1. 確定解空間的組織結構
  2. 從開始結點(根結點)出發,深度優先搜索整個解空間。(這個開始結點成為活結點,也為當前的擴展結點)
  3. 在當前擴展結點處,向縱深方向搜索一個新結點。(這個新結點成為活結點,也為當前的擴展結點)
    • 如果不能向縱深方向搜索了,則當前結點成為死結點。並且往回移動(回溯)到最近的活結點處
  4. 回溯法按上述方式遞歸地在解空間中搜索,直到找到所要求的解解空間中無活結點為止

如何避免回溯法的無效搜索

剪枝函數:

  • 約束函數 在擴展結點處剪去不滿足約束的子樹——0-1背包問題
  • 上界函數 剪去得不到最優解的子樹——TSP問題

遞歸回溯

void backtrack(int t)   // 遞歸深度t
{
    if(t > n)   // 最大深度n
        output(x);
    else
        for(int i = f(n, t); i <= g(n, t); ++i)
        {   // 在當前擴展結點處未搜索過的子樹
            x[t] = h(i);
            if(constrain(t) && bound(t))   // 約束函數 和 上界函數
                backtrack(t+1);
        }
}

迭代回溯

void iterativeBacktrack()
{   // 采用樹的非遞歸深度優先遍歷(樹的遍歷)
    stack<T> s;   // 存結點的堆棧
    T p = t;   // 當前擴展結點p,根結點t
	while(!s.empty())
    {
        for(int i = 0; i < p.child.size(); ++i)
        {   // 在當前擴展結點處未搜索過的子樹
            d = p.child[i];   // 子樹結點d
            if(constrain(d) && bound(d))   // 約束函數 和 上界函數
                s.push(d);
        }
        p = s.top();
        s.pop();
    }
}

子集樹和排列樹

  • 子集樹

    當所給問題是從n個元素的集合S中找出S滿足某種性質的子集時(選或不選某個結點),相應的解空間樹被稱為子集樹。

    如0-1背包問題,這類問題通常有2n個葉結點,其結點總數為2n+1-1。

    遍歷子集樹需要Ω(2n)計算時間

    image-20201118204948206


  • 排列樹

    當所給問題是確定n個元素滿足某種性質的排列時,相應的解空間樹被稱為排列樹。

    如旅行商問題TSP,這類問題通常有n! 個葉結點

    遍歷排列樹需要Ω(n!)計算時間



實例分析

旅行商問題 (排列樹)

  • 問題描述:

某銷售商要到若干個城市去推銷商品,已知各城市之間的路程(或費用)。要求為給旅行商選擇一條從駐地出發的路徑,經過每個城市一次,最后返回駐地,使得該路徑(或總的旅費)最短(或最小)。

  • 問題分析:

NP難問題。設𝐺=(𝑉,𝐸)是一個帶權圖。圖中各邊的權為正數。圖的一條周游路線是包括𝑉中的每個頂點在內的一條回路。周游路線的費用是這條路線上所有邊的權之和。——旅行商問題就是要在圖𝐺中找出費用最小的周游路線。

  • 實例分析:

對於n = 4的TSP問題,可能周游的路線有6條。

對於n = N的TSP問題,可能周游路線有(N-1)!條


  • 回溯法求解過程:

  • 剪枝函數的引入:

采用當前已知的最優解(費用X)為標准,若當前路徑長度 ≥ X,則表明以此結點為根結點的子樹中不包含最優解,將子樹中所有結點都設置為死結點,並向當前結點的最近祖先結點回溯。


  • 時間復雜度及算法:

O(n!)

常用TSP解決方案:遺傳算法;模擬退火;神經網絡;並行算法


騎士巡游問題(子集樹)

符號三角形問題(子集樹)

N皇后問題(子集樹)

最大團問題(子集樹)

圖的m着色問題(子集樹)

圓排列問題(排列樹)

電路板排列問題(排列樹)

連續郵資問題



回溯法效率分析

影響因素
  1. 產生 狀態點x[k] 的時間
  2. 滿足顯約束的 狀態點x[k] 的個數
  3. 計算約束函數constrain的時間
  4. 計算上界函數bound的時間
  5. 滿足約束函數和上界函數的所有結點個數

解空間的結構一旦確定,前3個因素就可以確定,剩下的就是考慮回溯過程中生成的結點個數

重排原理

在搜索試探時,選取x[i]的值順序是任意的。在其他條件相當的前期下,讓可取值最少的x[i]優先有效。這樣,在低層剪枝時,可以剪去更多的子樹,可提高回溯法效率。

概率方法估計將產生的結點數

原因:

對兩個非常相近的實例,其產生的結點數也會存在很大的差別


方案:

在解空間樹上產生一條隨機路徑,然后沿該路徑估算解空間中滿足約束條件的結點數m

多選取幾條不同的路徑,分別計算m,然后平均,估算更准確



小結

  1. 回溯法的基本思想

  2. 問題解空間的定義和組織

  3. 剪枝函數的設計

  4. 掌握利用回溯法求解問題的方法

  5. 效率分析

     

    PS: 本節內容偏於設計,於《算法導論》中無本章節,用於補充


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM