資料結構 練習 16-動態規劃 1

來源:互聯網
上載者:User

參考文獻 《演算法導論》 第15章

 

所謂“動態規劃“”,就是尋求最優解的過程,採用的也是遞迴的思想,不過與分而治之的區別是:分治法,每個子問題是獨立的,只要求出每個字問題,然後合并一下,就可以了;而動態規劃雖然也是遞迴的過程,但子問題不獨立,下文將結合例子講解。

根據《演算法導論》,動態規劃(dynamic programming) 包括一下四個方面:

1,描述最優解的結構

2,遞迴定義最優解的值

3,自底向上的方式計算最優解的值

4,有計算出的結果構造一個最優解。

還是引用書上的裝配調度來分析。不清楚題目的,請看原始第二版 P192

為了 找到最優路徑,如果我們採用笨辦法就是所有路徑都算一遍,當然肯定可以的,但是複雜度為O(2^n),電腦沒法接受。

在此背景下,動態規劃來了。

動態規劃的核心思想是:子問題最優,子子問題最優,不斷最優。而在最優的過程中,充分利用了,子問題之間的關係,避免重複計算。後一個最優一定是在前一個最優的基礎上建立的,而分治沒有。根本原因,在於,動態規劃針對的就是最優問題。當然分治法也可以針對最優,但是動態規劃在求最優方面是分治的進化,是更進階的東西。

據上面的例子:

假如分治法找到到a1,3的最短路徑,OK,所有遍曆:

e1    a1,1   a1,2    a1,3 

e 1   a1,1    a2,2   a1,3

e2    a2,1   a2,2    a1,3

e2    a2,1   a1,2    a1,3

假設採用動態規劃:

通向a1,3有倆條路徑,a1,2 和 a2,2

此時,分別計算通往a1,2  a2,2  的最優路徑,然後比較,再決定哪條路徑最優。

在此過程中,a1,2 到 a1,3隻計算一次,而在,分治法中,a1,2 到a1,3計算了倆次,如上第一行和第四行,依此原理其他路徑也只要計算一次;這樣計算量大大縮減,當然有的人會說,每個點增加了一次比較(選擇子最優)。

但是點到點之間的重複計算隨著規模的增大而增大。也正由於比較的存在,一個點一次,導致最後的複雜度為O(N)。

根據《演算法導論》給出遞推關係式:

下面嘗試給出代碼:

 我自己用遞迴函式寫的代碼

#include<iostream>using namespace std;//聲明幾個全域變數。一般不建議聲明全域變數,但這隻是功能測試。int a1[6]={7,9,3,4,8,4};int a2[6]={8,5,6,4,5,7};int t1[5]={2,3,1,3,4};int t2[5]={2,1,2,2,1};int e1=2;//進入網站的時間int e2=4;int x1=3;//退出網站的時間int x2=2;int l1[5];int l2[5];//記錄留個位置 int sum1;int sum2;//f1 路線1上到網站_a1的最優路徑的時間總和,_t1路徑轉移數組的下標,其餘類似void fastWay(int f1,int f2,int _t1,int _a1,int _t2,int _a2){  if(_t1>=5||_t2>=5|| _a1>=6|| _a2>=6) return;//遍曆完成int tmp1;int tmp2;tmp1=f2+t2[_t2]+a1[_a1];tmp2=f1+a1[_a1];int inputData1,inputData2;    if(tmp1>tmp2){        l1[_a1-1]=1;inputData1=tmp2;       }else{        l1[_a1-1]=2;inputData1=tmp1;}sum1=inputData1;tmp1=f1+t1[_t1]+a2[_a2];tmp2=f2+a2[_a2];if(tmp1>tmp2){l2[_a2-1]=2;inputData2=tmp2;}else{l2[_a2-1]=1;inputData2=tmp1;}sum2=inputData2;_t1++;_a1++;_t2++;_a2++;fastWay(inputData1,inputData2,_t1,_a1,_t2,_a2);}int main(){ int addedF1=e1+a1[0]; int addedF2=e2+a2[0]; fastWay(addedF1,addedF2,0,1,0,1); for(int i=0;i<5;++i) cout<<l1[i]; cout<<endl; for(int i=0;i<5;++i) cout<<l2[i];  if(sum1+x1>sum2+x2)    {cout<<"花的最少時間是:"<<sum2+x2<<"經過的網站為:";        for(int i=0;i<5;++i)        cout<<l2[i];cout<<2;    }  else   { cout<<"花的最少時間是:"<<sum1+x1<<"經過的網站為:";      for(int i=0;i<5;++i)        cout<<l1[i];cout<<1;   }    return 0;}

測試結果:

程式利用了函數的遞迴,需要反覆壓入棧,效率,不如直接迴圈高,如  http://www.cnblogs.com/Anker/archive/2013/03/09/2951785.html 寫的代碼 還是不錯的。

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.