動態規劃 詳解 帶例子

2021-06-27 05:19:58 字數 2662 閱讀 6955

動態規劃之例項一

如果我們有面值為1元、3元和5元的硬幣若干枚,如何用最少的硬幣湊夠11元? (表面上這道題可以用貪心演算法,但貪心演算法無法保證可以求出解,比如1元換成2元的時候)

首先我們思考乙個問題,如何用最少的硬幣湊夠i元(i<11)?為什麼要這麼問呢? 兩個原因:1.當我們遇到乙個大問題時,總是習慣把問題的規模變小,這樣便於分析討論。 2.這個規模變小後的問題和原來的問題是同質的,除了規模變小,其它的都是一樣的, 本質上它還是同乙個問題(規模變小後的問題其實是原問題的子問題)。

好了,讓我們從最小的i開始吧。當i=0,即我們需要多少個硬幣來湊夠0元。 由於1,3,5都大於0,即沒有比0小的幣值,因此湊夠0元我們最少需要0個硬幣。 (這個分析很傻是不是?別著急,這個思路有利於我們理清動態規劃究竟在做些什麼。) 這時候我們發現用乙個標記來表示這句「湊夠0元我們最少需要0個硬幣。」會比較方便, 如果一直用純文本來表述,不出一會兒你就會覺得很繞了。那麼, 我們用d(i)=j來表示湊夠i元最少需要j個硬幣。於是我們已經得到了d(0)=0, 表示湊夠0元最小需要0個硬幣。當i=1時,只有面值為1元的硬幣可用, 因此我們拿起乙個面值為1的硬幣,接下來只需要湊夠0元即可,而這個是已經知道答案的, 即d(0)=0。所以,d(1)=d(1-1)+1=d(0)+1=0+1=1。當i=2時, 仍然只有面值為1的硬幣可用,於是我拿起乙個面值為1的硬幣, 接下來我只需要再湊夠2-1=1元即可(記得要用最小的硬幣數量),而這個答案也已經知道了。 所以d(2)=d(2-1)+1=d(1)+1=1+1=2。一直到這裡,你都可能會覺得,好無聊, 感覺像做小學生的題目似的。因為我們一直都只能操作面值為1的硬幣!耐心點, 讓我們看看i=3時的情況。當i=3時,我們能用的硬幣就有兩種了:1元的和3元的( 5元的仍然沒用,因為你需要湊的數目是3元!5元太多了親)。 既然能用的硬幣有兩種,我就有兩種方案。如果我拿了乙個1元的硬幣,我的目標就變為了: 湊夠3-1=2元需要的最少硬幣數量。即d(3)=d(3-1)+1=d(2)+1=2+1=3。 這個方案說的是,我拿3個1元的硬幣;第二種方案是我拿起乙個3元的硬幣, 我的目標就變成:湊夠3-3=0元需要的最少硬幣數量。即d(3)=d(3-3)+1=d(0)+1=0+1=1. 這個方案說的是,我拿1個3元的硬幣。好了,這兩種方案哪種更優呢? 記得我們可是要用最少的硬幣數量來湊夠3元的。所以, 選擇d(3)=1,怎麼來的呢?具體是這樣得到的:d(3)=min。

package com.dp;

//應該可以優化,求大神指教

public class theminestcoin ;//取硬幣個數的最小值 動態規劃

*/public static void main(string args) ;

// 最少需要幾枚硬幣

int count=11;

numberofcoin(a, count);

} private static void numberofcoin(int a, int count)

}system.out.println(mincoin + " i="+i);

min[i]=mincoin;//時間複雜度為o(n^2)

} system.out.println(min[11]); }}

例項2 動態規劃之最長遞增子串行

package com.dp;

public class thelargestincreamentsubstring ,其中jlis[i])

}} int max=lis[0];

for(int i=1;imax)

}system.out.println(max);

//時間複雜度為o(n^2);

//優化

liss(a);

} private static void liss(int a) else

}lis[low]=a[i];

if(low>len)len++;

} for(int i=1;i<=len;i++)} }

3.最大子陣列和

public class thelargestsubhe ; 

int a=;

maxsubsum(a);

} private static void maxsubsum(int a)

}

最長公共子串行

引進乙個二維陣列c,用c[i][j]記錄x[i]與y[j] 的lcs 的長度,b[i][j]記錄c[i][j]是通過哪乙個子問題的值求得的,以決定搜尋的方向。

我們是自底向上進行遞推計算,那麼在計算c[i,j]之前,c[i-1][j-1],c[i-1][j]與c[i][j-1]均已計算出來。此時我們根據x[i] = y[j]還是x[i] != y[j],就可以計算出c[i][j]。

遞迴式

動態規劃例子

對於由從1到n 1 n 39 這n個連續的整數組成的集合來說,我們有時可以將集合分成兩個部分和相同的子集合。例如,n 3時,可以將集合 分為和。此時稱有一種方式 即與順序無關 n 7時,共有四種方式可以將集合 分為兩個部分和相同的子集合 和 和 和 和 輸入 程式從標準輸入讀入資料,只有一組測試用例...

動態規劃例子

演算法描述 已知多段圖的鄰接表,利用從後往前遞推的方法,先從最後一層往前保留當前的最短路徑長度,由子結構的最優解得到原問題的最優解。遞推公式是 cost i,j min 這裡為了節約空間,用一維陣列cost來儲存節點j到t的最短路徑長度。將所有節點按0 n 1進行編號,源點s為0,匯點t為n 1 向...

動態規劃經典例子

金明今天很開心,家裡購置的新房就要領鑰匙了,新房裡有一間他自己專用的很寬敞的房間。更讓他高興的是,媽媽昨天對他說 你的房間需要購買哪些物品,怎麼布置,你說了算,只要不超過n元錢就行 今天一早金明就開始做預算,但是他想買的東西太多了,肯定會超過媽媽限定的n元。於是,他把每件物品規定了乙個重要度,分為5...