動態(tài)規(guī)劃

動態(tài)規(guī)劃簡介

動態(tài)規(guī)劃算法與分治法類似,其基本思想也是將待求解問題分解成若干個子問題琼了,先求解子問題逻锐,然后從這些子問題的解得到原問題的解。與分治法不同的是雕薪,適合于動態(tài)規(guī)劃算法求解的問題昧诱,經(jīng)分解的得到的子問題往往不是相互獨(dú)立的。分治算法兩個自問題一般是不重疊的所袁。
??若用分治法來解這類問題盏档,則分解的得到的子問題數(shù)目太多,以至于最后解決原問題需要耗費(fèi)指數(shù)時間燥爷。在用分治法求解時蜈亩,有些子問題被重復(fù)計算了許多次。如果我們能夠保存已解決子問題的答案前翎,而在需要時再找出已求得的答案稚配,這樣就可以避免大量的重復(fù)計算。

自頂向下計算會產(chǎn)生重復(fù)計算的問題港华。比如要計算下圖中要計算a[i,j]為塔頂?shù)淖铀塬@得的最大路徑和道川。那么每走一層都要問下一層它走過最長的路徑是啥,紅框部分重疊就是為重復(fù)部分立宜,那么這部分就被至少問了2次以上愤惰。


動態(tài)規(guī)劃應(yīng)用

1. 計算最長公共子序列長度
??計算最長公共子序列長度的動態(tài)規(guī)劃算法LCSLength以序列X={x1,x2,...,xm}和Y={y1,y2,...,yn}作為輸入,計算得到數(shù)組c赘理,其中c[i][j]存儲序列Xi={x1,x2,...,xi}和序列Yj={y1,y2,...,yj}的最長公共子序列長度宦言。

解題思路
??設(shè)A="a[0]...a[m]",B="b[0]...b[n]"商模,并且Z="z[0]...z[k]"為它們最長公共子序列奠旺。在找A、B公共子序列時施流,若a[m]=b[n]响疚,則進(jìn)一步解決一個子問題:找"a[0]...a[m-1]"和"b[0]...b[n-1]"的最長公共子序列。若a[m]≠b[n]瞪醋,則要解決兩個子問題:找"a[0]...a[m-1]"和"b[0]...b[n]"的最長公共子序列和找"a[0]...a[m]"和"b[0]...b[n-1]"的最長公共子序列忿晕,再取兩者中較長者作為A和B的最長公共子序列。
??但LCSLength存在子問題重疊性質(zhì)银受,如在計算X和Y的LCSLength時践盼,可能要計算X和Y[n-1]及X[m-1]和Y的LCSLength鸦采,而這兩個子問題都包含了一個公共子問題,即計算X[m-1]和Y[n-1]的最長公共子序列咕幻。所以用c[i][j]記錄Xi和Yj的最長公共子序列的長度渔伯。當(dāng)i=0或j=0時,空序列時Xi和Yj的最長公共子序列肄程。故此時c[i][j]=0.其他情況下锣吼,由最優(yōu)子結(jié)構(gòu)性質(zhì)可建立遞歸關(guān)系如下:

代碼

void LSCLength(int m,int n,char *x,char *y,int **c){
   int i,j;
   for(i=1;i<=m;i++) c[i][0]=0;
   for(i=1;i<=n;i++) c[0][i]=0;
   for(i=1;i<=m;i++)          //自底向上計算
       for(j=1;j<=n;i++)
       {  
           if(x[i]==y[j]) { c[i][j] = c[i-1][j-1]+1; }
           else if(c[i-1][j] >= c[i][j-1])  c[i][j]=c[i-1][j]
           else { c[i][j]=c[i][j-1]; }
       }
}

時間復(fù)雜度
??由于每個數(shù)組單元的計算耗時為O(1)時間,算法LCSLength耗時O(mn)蓝厌。

2. 0-1背包問題
??0-1背包問題:給定n種物品和一背包玄叠。物品i的重量是wi,其價值為vi拓提,背包的容量為C读恃。問應(yīng)該如何選擇裝入背包中的物品,使得裝入背包中的物品的總價值最大崎苗?
??選擇裝入背包的物品時,對每種物品i只有兩種選擇舀寓,即裝入背包或不裝入背包胆数。不能將物品i裝入背包多次,也不能只裝入部分的物品i互墓。因此必尼,該問題成為0-1背包問題。

最優(yōu)子結(jié)構(gòu)性質(zhì)
??此問題的形式化描述是:給定C>0篡撵,wi>0判莉,vi>0,1<=i<=n育谬,要求找出一個n元0-1向量(x1券盅,x2,...膛檀,xn)锰镀,xi∈{0,1}咖刃,1<=i<=n泳炉,使得∑(i=1n)wixi<=C,而且∑(i=1n)vixi達(dá)到最大嚎杨。


??設(shè)(y1,y2,…,yn)是 (3.4.1)的一個最優(yōu)解.則(y2,…,yn)是下面相應(yīng)子問題的一個最優(yōu)解:

證明:使用反證法花鹅。若不然,設(shè)(z2,z3,…,zn)是上述子問題的一個最優(yōu)解枫浙,而(y2,y3,…,yn)不是它的最優(yōu)解刨肃。顯然有
???????????∑vizi > ∑viyi (i=2,…,n)
??且????????w1y1+ ∑wizi<= c
??因此????v1y1+ ∑vizi (i=2,…,n) > ∑ viyi, (i=1,…,n)
說明(y1,z2, z3,…,zn)是(3.4.1)0-1背包問題的一個更優(yōu)解——>導(dǎo)出(y1,y2,…,yn)不是背包問題的最優(yōu)解(因?yàn)榇笄疤嵋呀?jīng)是(y1,y2,…,yn)是 (3.4.1)的一個最優(yōu)解古拴,而現(xiàn)在又導(dǎo)出一個(y1,z2, z3,…,zn)是(3.4.1)的最優(yōu)解,所以是前后矛盾的)之景,矛盾斤富。

解題思路
??有編號分別為a,b,c,d,e的五件物品,它們的重量分別是2,2,6,5,4锻狗,它們的價值分別是6,3,5,4,6满力,現(xiàn)在給你個承重為10的背包,如何讓背包里裝入的物品具有最大的價值總和轻纪?


首先要明確這張表是至底向上油额,從左到右生成的。為了敘述方便刻帚,用e2單元格表示e行2列的單元格潦嘶,這個單元格的意義是用來表示只有物品e時,有個承重為2的背包崇众,那么這個背包的最大價值是0掂僵,因?yàn)閑物品的重量是4,背包裝不了顷歌。對于d2單元格锰蓬,表示只有物品e,d時,承重為2的背包,所能裝入的最大價值眯漩,仍然是0芹扭,因?yàn)槲锲積,d都不是這個背包能裝的。
??同理赦抖,c2=0舱卡,b2=3,a2=6。對于承重為8的背包队萤,a8=15,是怎么得出的呢轮锥?根據(jù)01背包的狀態(tài)轉(zhuǎn)換方程,需要考察兩個值要尔,一個是f[i-1,j],對于這個例子來說就是b8的值9交胚,另一個是f[i-1,j-Wi]+Pi。
??在這里盈电, f[i-1,j]表示我有一個承重為8的背包蝴簇,當(dāng)只有物品b,c,d,e四件可選時,這個背包能裝入的最大價值匆帚。f[i-1,j-Wi]表示我有一個承重為6的背包(等于當(dāng)前背包承重減去物品a的重量)熬词,當(dāng)只有物品b,c,d,e四件可選時,這個背包能裝入的最大價值。f[i-1,j-Wi]就是指單元格b6,值為9互拾,Pi指的是a物品的價值歪今,即6。由于f[i-1,j-Wi]+Pi = 9 + 6 = 15 大于f[i-1,j] = 9颜矿,所以物品a應(yīng)該放入承重為8的背包寄猩。
??設(shè)所給0-1背包問題的子問題的最優(yōu)值為m(i,j)骑疆,即m(i,j)是背包容量為j田篇,可選擇物品物品為i,i+1箍铭,...泊柬,n時0-1背包問題的最優(yōu)值。有0-1背包問題的最優(yōu)子結(jié)構(gòu)性質(zhì)诈火,可以建立計算m(i,j)的遞歸式如下:

在max{m(i+1,j),m(i+1,j-wi)+vi}中兽赁,m(i+1,j)代表不選當(dāng)前物品,而m(i+1,j-wi)+vi代表選擇當(dāng)前物品(加上當(dāng)前物品價值)冷守。如果當(dāng)前物品重量比背包總?cè)萘窟€打的話刀崖,那就只能是m(i+1,j)。

代碼
??當(dāng)wi(1<=i<=n)為正整數(shù)時拍摇,用二維數(shù)組m[][]來存儲m(i,j)的相應(yīng)值亮钦,可設(shè)計解0-1背包問題的動態(tài)規(guī)劃算法 Knapsack如下:

//n為物品個數(shù),c為背包容量
void Knapsack(Type v, int w , int c , int n , Type **m)
{
   int jMax = min(w[n]-1,c);  //比較背包容量和當(dāng)前物品的重量

   /**先初始化下標(biāo)最大(n)的**/
   //初始化背包容量從0到j(luò)Max的最優(yōu)值
   for(int j=0; j<=jMax; j++)  m[n][j] = 0; 
   //初始化背包容量>=當(dāng)前物品重量時m[n][j]的值(若背包容量<當(dāng)前物品則保留為0)
   for(int j=w[n]; j<=c; j++)  m[n][j] = v[n];

   /**計算下標(biāo)比n小的**/
   for(int i = n-1; i>1 ; i--){
     jMax = min(w[i]-1,c);
     //沒選之前授翻,m[i][j]皆為前面選的價值總和
     for(int j=0; j<=jMax; j++)  m[i][j] = m[i+1][j];
     //j從放得下本物品開始的容量開始
     for(int j=w[i]; j<=c; j++)  m[i][j] = max(m[i+1][j],m[i+1][j-w[i]]+v[i]);
   }
   m[1][c] = m[2][c];
   if(c>=w[1]) m[1][c] = max(m[1][c],m[2][c-w[1]]+v[1]);
}

//構(gòu)造相應(yīng)的最優(yōu)解
void Traceback(Type **m, int w , int c, int n, int x)
{
  for(int i=1;i<=n;i++)
    if(m[i][c]==m[i+1][c]) x[i] = 0;
    else { x[i] = 1;c-=w[i]; }
  x[n] = (m[n][c])?1:0;
}

算法Knapsack計算后或悲,m[1][c]給出所要求的0-1背包問題的最優(yōu)值孙咪。相應(yīng)的最優(yōu)解可由算法Traceback計算如下堪唐。如果m[1][c]=m[2][c],則x1=0翎蹈,否則x1=1淮菠。當(dāng)x1=0時,由m[2][c]繼續(xù)構(gòu)造最優(yōu)解荤堪。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末合陵,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子澄阳,更是在濱河造成了極大的恐慌拥知,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碎赢,死亡現(xiàn)場離奇詭異低剔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進(jìn)店門襟齿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來姻锁,“玉大人,你說我怎么就攤上這事猜欺∥涣ィ” “怎么了?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵开皿,是天一觀的道長涧黄。 經(jīng)常有香客問我,道長副瀑,這世上最難降的妖魔是什么弓熏? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮糠睡,結(jié)果婚禮上挽鞠,老公的妹妹穿的比我還像新娘。我一直安慰自己狈孔,他們只是感情好信认,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著均抽,像睡著了一般嫁赏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上油挥,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天潦蝇,我揣著相機(jī)與錄音,去河邊找鬼深寥。 笑死攘乒,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的惋鹅。 我是一名探鬼主播则酝,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼闰集!你這毒婦竟也來了沽讹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤武鲁,失蹤者是張志新(化名)和其女友劉穎爽雄,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沐鼠,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡挚瘟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片刽沾。...
    茶點(diǎn)故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡本慕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出侧漓,到底是詐尸還是另有隱情锅尘,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布布蔗,位于F島的核電站藤违,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏纵揍。R本人自食惡果不足惜顿乒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望泽谨。 院中可真熱鬧璧榄,春花似錦、人聲如沸吧雹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雄卷。三九已至搓蚪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丁鹉,已是汗流浹背妒潭。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留揣钦,地道東北人雳灾。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像拂盯,于是被迫代替她去往敵國和親佑女。 傳聞我的和親對象是個殘疾皇子记靡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容