精品伊人久久大香线蕉,开心久久婷婷综合中文字幕,杏田冲梨,人妻无码aⅴ不卡中文字幕

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
【算法復習二】傳統基本算法(貪心、動態規劃、回溯和分支限界)

 一,貪心算法的設計思想

        · 從問題的某一個初始解出發逐步逼近給定的目標,每一步都作一個不可回溯的決策,盡可能地求得最好的解。當達到某算法中的某一步不需要再繼續前進時,算法停止。


二,貪心算法的基本性質

       1)貪心選擇性質

             所謂貪心選擇性質是指所求問題的整體最優解可以通過一系列局部最優的選擇,即貪心選擇來達到。這是貪心算法可行的第一個基本要素,也是貪心法與動態規劃法的主要區別。

       2) 最優子結構性質

           該問題解的整體最優性依賴于其局部子問題解的最優性。這種性質是可以采用貪心算法解決問題的關鍵特征。例如,活動安排問題,在選擇了一項活動后,它必須是最優的,否則不能得到全局的最優。


三,貪心算法的適用性

        · 貪心算法對問題只需考慮當前局部信息就要做出決策,也就是說使用貪心算法的前提是局部最優策略能導致產生全局最優解

        ·該算法的適用范圍較小若應用不當不能保證求得問題的最佳解。更準確的方法是通過數學方法證明問題對貪心策略的選用性。


四,絕對貪心問題

        例一:Dijkstra單源最短路徑問題(有向圖)  

      (Dijkstra)算法思想  按路徑長度遞增次序產生最短路徑算法:  把V分成兩組:  (1)S:已求出最短路徑的頂點的集合  (2)V-S=T:尚未確定最短路徑的頂點集合   將T中頂點按最短路徑遞增的次序加入到S中   保證:1)從源點V0到S中各頂點的最短路徑長度都不大于 從V0到T中任何頂點的最短路徑長度             2)每個頂點對應一個距離值  S中頂點:從V0到此頂點的最短路徑長度     T中頂點:從V0到此頂點的只包括S中頂點作中間 頂點的最短路徑長度  依據:可以證明V0到T中頂點Vk的最短路徑,或是從V0到Vk的 直接路徑的權值;或是從V0經S中頂點到Vk的路徑權值之和   求最短路徑步驟  算法步驟如下:  1. 初使時令 S={V0},T={其余頂點},T中頂點對應的距離值  若存在<V0,Vi>,d(V0,Vi)為<V0,Vi>弧上的權值  若不存在<V0,Vi>,d(V0,Vi)為∝  2. 從T中選取一個其距離值為最小的頂點W且不在S中,加入S  3. 對T中頂點的距離值進行修改:若加進W作中間頂點,從V0到Vi的 距離值比不加W的路徑要短,則修改此距離值  重復上述步驟2、3,直到S中包含所有頂點,即S=T為止


        輔助數組:dist[ ] 存放V0到T中點距離  

                          path[ ]存放已經加入S中點到V0最短路徑


        例二:Kruskal最小生成樹問題(每次選權值最小邊,直到生成一個最小生成樹)

                  算法的運行時間為 O(nlog n)

         源碼:

  1. #include<stdio.h>  
  2. #include<stdlib.h>  
  3. #include<string.h>  
  4. #define MAX_NAME 5  
  5. #define MAX_VERTEX_NUM 20   
  6. typedef char Vertex[MAX_NAME];/*頂點名字串*/  
  7. typedef int AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];/*鄰接距陣*/  
  8. struct MGraph/*定義圖*/  
  9. {  
  10.  Vertex vexs[MAX_VERTEX_NUM];   
  11.  AdjMatrix arcs;   
  12.  int vexnum,arcnum;   
  13. };  
  14.   
  15. typedef struct  
  16. {   
  17.   Vertex adjvex; /*當前點*/  
  18.   int lowcost;    /*代價*/  
  19. }minside[MAX_VERTEX_NUM];  
  20.   
  21. int LocateVex(MGraph G,Vertex u)//定位  
  22. {   
  23.   int i;  
  24.   for(i=0;i<G.vexnum;++i)if(strcmp(u,G.vexs[i])==0)return i;  
  25.   return -1;  
  26. }  
  27.   
  28. void CreateGraph(MGraph &G)  
  29. {  
  30.   int i,j,k,w;  
  31.   Vertex va,vb;  
  32.   printf("請輸入無向網G的頂點數和邊數(以空格為分隔)\n");  
  33.   scanf("%d %d",&G.vexnum,&G.arcnum);  
  34.   printf("請輸入%d個頂點的值(<%d個字符):\n",G.vexnum,MAX_NAME);  
  35.   for(i=0;i<G.vexnum;++i) /* 構造頂點集*/  
  36.     scanf("%s",G.vexs[i]);  
  37.   for(i=0;i<G.vexnum;++i) /*初始化鄰接矩陣*/  
  38.     for(j=0;j<G.vexnum;++j)  
  39.       G.arcs[i][j]=0x7fffffff;   
  40.   printf("請輸入%d條邊的頂點1 頂點2 權值(以空格作為間隔): \n",G.arcnum);  
  41.   for(k=0;k<G.arcnum;++k)  
  42.   {  
  43.     scanf("%s%s%d%*c",va,vb,&w);   
  44.     i=LocateVex(G,va);  
  45.     j=LocateVex(G,vb);  
  46.     G.arcs[i][j]=G.arcs[j][i]=w; /*對稱*/  
  47.   }  
  48. }  
  49.  void kruskal(MGraph G)  
  50.  {  
  51.    int set[MAX_VERTEX_NUM],i,j;  
  52.    int k=0,a=0,b=0,min=G.arcs[a][b];  
  53.    for(i=0;i<G.vexnum;i++)  
  54.      set[i]=i;  
  55.    printf("最小代價生成樹的各條邊為:\n");  
  56.    while(k<G.vexnum-1)   
  57.    {   
  58.      for(i=0;i<G.vexnum;++i)  
  59.        for(j=i+1;j<G.vexnum;++j)  
  60.        if(G.arcs[i][j]<min)  
  61.        {  
  62.          min=G.arcs[i][j];   
  63.          a=i;   
  64.          b=j;   
  65.        }  
  66.      min=G.arcs[a][b]=0x7fffffff;   
  67.      if(set[a]!=set[b])  
  68.      {  
  69.        printf("%s-%s\n",G.vexs[a],G.vexs[b]);   
  70.        k++;   
  71.        for(i=0;i<G.vexnum;i++)  
  72.          if(set[i]==set[b])   
  73.            set[i]=set[a];  
  74.      }  
  75.    }  
  76.  }  
  77.   
  78. int main()  
  79.  {  
  80.    MGraph g;  
  81.    CreateGraph(g);   
  82.    kruskal(g);   
  83.    system("PAUSE");  
  84.    return 0;  
  85.  }  
  86. /*結果如下  
  87. 請輸入無向網G的頂點數和邊數(以空格為分隔)  
  88. 6 10  
  89. 請輸入6個頂點的值(<5個字符):  
  90. v1  
  91. v2  
  92. v3  
  93. v4  
  94. v5  
  95. v6  
  96. 請輸入10條邊的頂點1 頂點2 權值(以空格作為間隔):  
  97. v1 v2 6  
  98. v1 v3 1  
  99. v1 v4 5  
  100. v2 v3 5  
  101. v2 v5 3  
  102. v4 v3 5  
  103. v4 v6 2  
  104. v3 v5 6  
  105. v3 v6 4  
  106. v5 v6 6  
  107. 最小代價生成樹的各條邊為:  
  108. v1-v3  
  109. v4-v6  
  110. v2-v5  
  111. v3-v6  
  112. v2-v3  
  113. 請按任意鍵繼續. . .  
  114. */  
  

五,相對貪心問題

       例一,取數游戲。

        ·問題描述

                2個人輪流取2n個數中的n個數,取數之和大者為勝。設計算法,讓先取數者獲勝,模擬取數過程。

        ·問題分析

                這個游戲一般假設取數者只能看到2n個數中兩邊的數(第一次取時,能看到6,5則取6),用貪心算法的情況:

        ·例如

               若一組數據為:6,16,27,6,12,9,2,11,6,5

               用貪心策略每次兩人都取兩邊的數中較大的一個數,先取者勝.以A先取為例:

               取數結果為:

                      A  6,27,12,5,11=61  勝

                      B  16,6,9,6,2=39

              ·但若選另一組數據:16,27,7,12,9,2,11,6

               仍都用貪心算法,先取者A敗。

               取數結果為:

                        A  16,7,9,11=43

                        B  27,12,6,2=47 勝

           其實,若我們只能看到兩邊的數據,則此題無論先取還是后取都無必勝的策略。這時一般的策略是用近似貪心算法

           但若取數者能看到全部2n個數,則此問題可有一些簡單的方法,有的雖不能保證所取數的和是最大,但確是一個先取者必勝的策略。


六,動態規劃(各個問題包含公共子問題)

       1)最優決策原理:要求問題具有最優子結構(即最優解包含子問題的最優解),是一種自底向上的求解思路,與遞歸正好相反,每次求解到一個階段時,該階段求解所依賴的子問題已經完全求解完畢,因此每一步的求解都是在直到全部所需信息的情況下進行的,因此可以得到全局最優解。

       2)動態規劃的決策過程:最優決策是在最后階段形成的,然后向前倒推,直到初始階段;而決策的具體結果及所產生的狀態轉移,卻是由初始階段開始進行計算的,然后向后遞歸或迭代,直到最終結果。

       3)適用條件

         任何思想方法都有一定的局限性,超出了特定條件,它就失去了作用。同樣,動態規劃也并不是萬能的。適用動態規劃的問題必須滿足最優化原理和無后效性。         1.最優化原理(最優子結構性質) 最優化原理可這樣闡述:一個最優化策略具有這樣的性質,不論過去狀態和決策如何,對前面的決策所形成的狀態而言,余下的諸決策必須構成最優策略。簡而言之,一個最優化策略的子策略總是最優的。一個問題滿足最優化原理又稱其具有最優子結構性質。         2.無后效性:將各階段按照一定的次序排列好之后,對于某個給定的階段狀態,它以前各階段的狀態無法直接影響它未來的決策,而只能通過當前的這個狀態。換句話說,每個狀態都是過去歷史的一個完整總結。這就是無后向性,又稱為無后效性。

         3.子問題的重疊性:動態規劃將原來具有指數級復雜度的搜索算法改進成了具有多項式時間的算法。其中的關鍵在于解決冗余,這是動態規劃算法的根本目的。 動態規劃實質上是一種以空間換時間的技術,它在實現的過程中,不得不存儲產生過程中的各種狀態,所以它的空間復雜度要大于其它的算法

 

     例題:著名的貨郎擔(旅行售貨商)問題

                 詳細解答參見博文------貨郎擔(旅行售貨商)

 

 

七,回溯

        1)設計思想

              回溯與分支限界技術實際上都是基于窮舉方法的,即按照一定規律,把問題所有可能的解組織成某種樹結構,形成可能的解空間樹或狀態空間樹。然后按照具體問題的約束條件,通過各種搜索策略,遍歷可能的解空間樹。從而得到滿足問題條件的解或最優解。兩種算法設計思路相近、本質一致。

        2)回溯與分支限界法解決實際問題,大致可分為四個環節:

             (1)確定問題的可能解空間,相當于找出進行窮舉的搜索范圍。

             (2)以一種便于搜索的方式組織所有的可能解,一般是生成可能解空間樹

             (3)以某種方式搜索可能的解空間樹,有兩種基本搜索方式。即:深度優先搜索方式和,這就是回溯技術;廣度優先搜索,就是分支限界技術。

             (4)在搜索過程中利用判定函數,也稱為限界函數,通過“剪枝”來加速搜索過程

       3)回溯法的設計原理

             按照深度優先搜索的方式,從根結點出發搜索狀態空間樹。

             ·   每搜索到達狀態空間樹的一個擴展結點,總是先判斷以該結點為根的子樹是否包含問題的解。如果肯定不包含,則跳過對該結點為根的子樹的進一步搜索,該結點成為一個死結點,同時應向上層回溯至最近的一個活動結點。再以該活動結點作為當前新的擴展結點。以這種方式遞歸地在解空間中搜索,直至找到問題的解,或者解空間中已無活動結點為止,即此問題無解。

             ·   在回溯法中,為了避免生成那些不可能產生最佳解的問題狀態,要不斷地利用限界函數來處死那些實際上不可能產生所需解的活動結點,以減少問題的計算量。所以,回溯法應是具有限界函數的深度優先搜索法。

             用回溯法解題時,常遇到兩類典型的解空間樹,子集樹與排列樹。

  

         例題:著名的八皇后問題

                    詳細解答參見博文------八皇后問題

 

八,分支限界(求問題在某種意義下的最優解

       1)分支限界法的設計原理

             分支限界法類似于回溯法,也是一種在問題的狀態空間樹上搜索解的算法。但是,分支限界法與回溯法有不同的求解目標。回溯法的求解目標是找出狀態空間樹中的所有回答結點或任一回答結點,分支限界法的求解目標則是找出使得某一目標函數達到極小或極大的一個問題結點

       2)分支限界法與回溯法有兩點不同:

           1)求解目標不同。回溯法的求解目標是找出解空間樹中滿足約束條件的所有解,而分支限界法的求解目標則是找出滿足約束條件的一個解或最優解

           (2)搜索方式不同。回溯法以深度優先的方式搜索解空間樹,而分支限界法則以廣度優先或以最小耗費優先的方式搜索解空間樹。

      3)常見的兩種分支限界法

          (1)隊列式(FIFO)分支限界法
                  按照隊列先進先出(FIFO)原則選取下一個結點為擴展結點。
          (2)優先隊列式分支限界法
                  按照優先隊列中規定的優先級選取優先級最高的結點成為當前擴展結點。
     4)常見問題

            裝箱問題、布線問題、單源最短路徑問題、最大團問題、0-1背包問題、旅行售貨問題


本站僅提供存儲服務,所有內容均由用戶發布,如發現有害或侵權內容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
算法分析與設計
五大算法總結
遞歸算法向非遞歸算法轉換
算法設計方法概覽
常見的算法設計策略
9、深度優先算法,圖的遍歷
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯系客服!

聯系客服

主站蜘蛛池模板: 温州市| 东丽区| 大竹县| 宁都县| 格尔木市| 乐至县| 建始县| 蕉岭县| 宁远县| 肇州县| 华宁县| 凤山县| 潢川县| 合肥市| 天水市| 嘉定区| 宝山区| 自治县| 莱州市| 杂多县| 陕西省| 曲阜市| 汤阴县| 临湘市| 许昌县| 米林县| 鸡西市| 聊城市| 合作市| 宁乡县| 达日县| 五寨县| 高安市| 巧家县| 曲周县| 大田县| 维西| 邳州市| 新干县| 兰考县| 会同县|