日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法笔记之回溯法(2)

發布時間:2025/3/21 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法笔记之回溯法(2) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

著色問題

問題分析

假設地圖共有7個區域,分別是A/B/C/D/E/F/G,對上面順序進行編號,每個區域用一個結點表示,相鄰的區域有連線,那么地圖就轉化成一個無向連接圖。

算法設計

  • 定義問題的解空間。圖的m著色問題解空間形式為n元組{x1,x2,...,xi,...,xn},每個分量取值為1,2,3,...,m,即問題的解是一個n元向量。由此可得,問題的解空間為{x1,x2,...,xi,...,xn},其中顯約束為xi=1,2,...,m。
  • 確定解空間的組織結構:一顆滿m叉樹,樹的深度為n。
  • 搜索解空間

    • 約束條件:假設當前擴展結點位于解空間樹的第t層,那么從第1到第t-1層的結點情況都已經確定,接下來是按照擴展結點的第一個分支進行擴展,此時需要判斷是否將第t個結點著色情況。第t個結點的色號要與前t-1個結點中與其有邊相連的結點顏色不同,如果有顏色相同的,則第t個結點不能用這個色號,換下一個色號嘗試。
    • 限界條件:無。
    • 搜索過程:擴展結點沿著第一個分支擴展,判斷約束條件,滿足則進入深一層繼續搜索;如果不滿足,則擴展生成的結點被剪掉,換下一個色號嘗試。如果所有色號都嘗試完畢,該結點變成死結點,向上回溯到距離其最近的活結點,繼續搜索。搜索到葉子結點時,找到一種著色方案,搜索過程直到全部活結點變成死結點為止。
  • 解題過程

    地圖7個區域,3種顏色。

  • 開始搜索第1層(t=1)。擴展A結點第一個分支,首先判斷是否滿足約束條件,因為之前還未著色任何結點,所以滿足約束條件,擴展該分支,令1號結點著1號色,即x[1]=1,生成B。
  • 拓展B結點(t=2)。擴展第一個分支x[2]=1,首先判斷2號結點是否和前面已經確定色號的結點(1號)有邊相連且色號相同,不滿足約束條件,剪掉該分支,然后沿著x[2]=2擴展,2號結點和前面已經確定色號的結點(1號)有邊相連,但色號不同,滿足約束條件,擴展該分支,令x[2]=2。
  • 擴展C結點(t=3)。擴展第一個分支x[3]=1,首先判斷3號結點是否和前面已經確定色號的結點(1、2號)有邊相連且色號相同,不滿足約束條件,剪掉該分支;同理剪掉x[3]=2分支。然后沿著x[3]=3擴展,3號結點和前面已經確定色號的結點(1、2號)有邊相連,但色號不同,滿足約束條件,擴展該分支,令x[3]=3。生成D。
  • 擴展D結點(t=4)。擴展第一個分支x[4]=1,首先判斷4號結點是否和前面已經確定色號的結點(1、2、3號)有邊相連且色號相同,不滿足約束條件(4余1相連),剪掉該分支;然后令x[4]=2,符合條件,生成E。
  • 擴展E結點(t=5)。擴展第一個分支x[5]=1,首先判斷4號結點是否和前面已經確定色號的結點(1、2、3號)有邊相連且色號相同,確定5與2、3、4相連但色號不同,滿足約束條件,擴展該分支,生成F。
  • 擴展F結點(t=6)。擴展第一個分支x[6]=1,同理不滿足,剪掉分支;然后沿著x[6]=2擴展,6與5號有邊相連但色號不同,故滿足約束條件,擴展該分支,令x[6]=2,生成G。
  • 擴展G結點(t=7)。擴展第一個分支x[7]=1,剪掉x[7]=1和x[7]=2的分支,然后令x[7]=3,符合要求,生成H。
  • 擴展H結點(t=8)。t>n,找到一個可行解,輸出該可行解{1,2,3,2,1,2,3},回溯到最近的活結點G。
  • 重新擴展G結點(t=7)。G已經考察完畢,成為死結點,回溯到最近的活結點F。
  • 繼續搜索,又找到第二種著色方案,輸出可行解{1,3,2,3,1,3,2}。
  • 繼續搜索,又找到4個可行解。
  • 代碼實現

    //約束條件 bool isRight(int t) {for (int j = 1; j < t; j++){if (map[t][j]){if (x[j] == x[t])return false;}}return true; }//回溯方法函數 void Backtrack(int t) {if (t > n){sum++;cout << "第" << sum << "種方案:";for (int i = 1; i <= n; i++)//輸出該著色方案{cout << x[i] << " ";}cout << endl;}else {for (int i = 1; i <= m; i++){x[t] = i;if (isRight(t))Backtrack(t + 1);}} }

    算法復雜度分析

  • 時間復雜度:O(nmn)。
  • 空間復雜度:O(n)。
  • n皇后問題

    問題介紹

    在n×n的棋盤上放置彼此不受攻擊的n個皇后。按照國際象棋規則,皇后可以攻擊與之在同一行、同一列、同一斜線上的棋子。現在在n*n的棋盤上放置n個皇后,使其不受攻擊。

    問題分析

    求解策略:
    以行為主導:

    • 在第1行第1列放置第一個皇后。
    • 在第2行放置第2個皇后。第2個皇后的位置不能和前面的皇后同列、同斜線,不用再判斷同行了,因為每行我們本來就只放一個。
    • 在第3行放置第3個皇后。第3個皇后的位置不能和前面的皇后同列、同斜線。
    • ……
    • 在第t行放置第t個皇后。第t個皇后的位置不能和前面的皇后同列、同斜線。
    • ……
    • 在第n行放置第n個皇后。第n個皇后的位置不能和前面的皇后同列、同斜線。

    算法設計

    (1)定義問題的解空間。n皇后問題解的形式為n元組:{x1,x2,...,xi,...,xn},分量xi表示第i個皇后放置在第i行第xi列,xi取值為1,2,3,...,n。顯約束為不同行。

    (2)解空間的組織結構:一顆m(m=n)叉樹,樹深度為n。

    (3)搜索解空間。
    約束條件:在第t行放置第t個皇后時,第t個皇后的位置不能和前t-1個皇后同列、同斜線。第i個皇后和第j個皇后不同列,即xi!=xj

    限界條件:不需要設置。

    搜索過程:

    從根開始,以DFS的方式進行搜索。根節點是活結點,并且是當前的擴展結點。在搜索過程中,當前的擴展結點沿縱深方向移向一個新結點,判斷該新結點是否滿足隱約束。如果滿足,則該新結點成為活結點,并且成為當前的擴展結點,繼續深一層的搜索;如果不滿足,則換到該新結點的兄弟結點繼續搜索;如果新結點沒有兄弟結點,或其兄弟結點已全部搜索完畢,則擴展結點成為死結點,搜索回溯到其父結點處繼續進行。搜索過程直到找到問題的根結點變成死結點為止。

    代碼實現

    bool isPlace(int t) {bool place = true;for (int j = 1; j < t; j++){if (x[t] == x[j] || t - j == fabs(x[t] - x[j]))//判斷列、對角線是否沖突{place = false;break;}}return place; }void backtrack(int t) {if (t > n){countn++;for (int i = 1; i <= n; i++){cout << x[i] << " ";}cout << endl;cout << "---------" << endl;}else{//分別判斷n個分支,特別注意i不要定義為全局變量,否則遞歸調用有問題for (int i = 1; i <= n; i++){x[t] = i;if (isPlace(t))backtrack(t + 1);//上面說的是不沖突就進行下一行搜索}} }

    算法復雜度分析

  • 時間復雜度:O(nn+1)。
  • 空間復雜度:O(n)。
  • 最優加工順序

    問題描述

    現在有3個機器零件{J1,J2,J3},在第一臺機器上的加工時間分別為2、5、4,在第二臺機器上的加工時間分別為3、1、6.如何安排零件加工順序,使第一個零件從機器1上加工開始到最后一個零件在機器2上加工完成,所需的總加工時間最短?

    問題分析

    我們通過分析可以發現,第一臺機器可以連續加工,而第二臺機器開始加工的時間是當前第一臺機器的下線時間第二臺機器下線時間最大值
    實際上就是找到n個機器零件的一個排列,使總的加工時間最短。

    算法設計

  • 定義問題的解空間。解的形式為n元組:{x1,x2,...,xi,...,xn},分量xi表示第i個加工的零件號,n個零件組成的集合為S={1,2,...,n},xi取值為S-{x1,x2,...,xi-1}。
  • 解空間的組織形式為一顆排列數,深度為n。
  • 搜索解空間。

    • 約束條件:無約束條件。
    • 限界條件:用f2表示當前已完成的零件在第二臺機器加工結束所用的時間,用bestf表示當前找到的最優加工方案的完成時間。顯然,繼續向深處搜索時,f2不會減少,只會增加。因此,當f2≥bestf時,沒有繼續向深處搜索的必要。限界條件可以描述為:f2。f2初值為0,bestf的初值為無窮大。
  • 搜索過程。擴展結點沿著某個分支擴展時需要判斷限界條件,如果滿足,則進入深一層繼續搜索;如果不滿足,則剪掉該分支。搜索到葉子結點的時候,即找到當前最優解。搜索直到全部活結變成死結點為止。
  • 代碼實現

    1.數據結構

    struct node {//機器零件在第一臺機器上的加工時間x和第二胎機器上的加工時間yint x,y; }T[MAX];

    2.按限界條件進行搜索求解:t表示當前擴展結點在第t層,f1表示當前第一臺機器上加工的完成時間,f2表示當前第二臺機器上加工的完成時間。如果t>n表示已經到達葉子結點,記錄最優值和最優解,返回。否則,分別判斷每個分支是否滿足約束條件,若滿足則進入下一層backtrack(t+1);如果不滿足則反操作復位,考察下一個分支(兄弟結點)。

    void Backtrack(int t) {if(t>n){for(int i=1;i<=n;i++)bestx[i]=x[i];//記錄最優隊列bestf=f2;//更新最優值return ;}for(int i=t;i<=n;i++){f1+=T[x[i].x;int temp=f2;f2=max(f1,f2)+T[x[i]].y;if(f2<bestf)//滿足限界條件{swap(x[t],x[i]);//交換Backtrack(t+1);//繼續搜索swap(x[t],x[i]);//復位,反操作}f1-=T[x[i]].x;//復位,反操作f2=temp;//復位,反操作} }

    算法復雜度分析

    時間復雜度為O(nn!)≈O((n+1)!),空間復雜度為O(n)。

    算法優化改進

    新的算法的時間復雜度為O(nlogn),空間復雜度為O(n)。利用貝爾曼規則,代碼如下:

    #include<iostream> #include<algorithm> using namespace std ; const int MX=10000+5 ; int n; struct node {int id;int x,y; }T[MX] ; bool cmp(node a,node b) {return min(b.x,a.y)>=min(b.y,a.x);//按照貝爾曼規則排序 } int main() {cout<<"請輸入機器零件的個數 n:";cin>>n;cout<<"請依次輸入每個機器零件在第一臺機器上的加工時間x和第二臺機器上的加工時間y:";for(int i=0;i<n;i++){cin>>T[i].x>>T[i].y;T[i].id=i+1;}sort(T,T+n,cmp); //排序int f1=0,f2=0;for(int i=0;i<n;i++) //計算總時間{f1+=T[i].x;f2=max(f1,f2)+T[i].y;}cout<<"最優的機器零件加工順序為:";for(int i=0;i<n;i++) //輸出最優加工順序cout<<T[i].id<<" ";cout<<endl;cout<<"最優的機器零件加工的時間為:";cout<<f2<<endl;return 0 ; }

    總結

    以上是生活随笔為你收集整理的算法笔记之回溯法(2)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。