動態規劃0-1揹包
1.
(1)動態規劃將問題劃分成子問題,在合併的結果。子問題是彼此獨立的。
(2)動態規劃將已計算過的子問題結果儲存到表中,是一種以空間換時間的方式。
(3)動態規劃的初始化條件注意,不要寫錯。找出遞迴函式關係式
(4)與記憶搜尋相比,動態規劃的計算具有一定的順序性,比如b的結果依賴a的結果,要先a在b,而記憶搜尋哪個先來就先計算哪個,將其結果儲存即可。
2、常見的動態規劃問題:
零一揹包問題
最長公共子序列LCS問題
最長升序子序列LIS問題
零錢問題
臺階問題
Floyd演算法
3.0-1揹包:
題目:一個揹包有一定的承重cap,有N件物品,每件都有自己的價值,記錄在陣列v中,也都有自己的重量,記錄在陣列w中,每件物品只能選擇要裝入揹包還是不裝入揹包,要求在不超過揹包承重的前提下,選出物品的總價值最大。給定物品的重量w價值v及物品數n和承重cap。請返回最大總價值。
[1,2,3],[1,2,3],3,6返回:6
思路:
N件物品,每一件有自己的重量和自己的價值,分別用一個陣列給出,揹包有一個限制總重量為cap,要求在滿足重量不超過cap的前提下,向背包中裝入物品,使得總的價值最大,求出最大價值
dp[i][j],即使用前i個物品,在重量不超過j時的最大價值為dp[i][j],注意對於重量,由於只給定了最大的範圍cap,但是在分解問題時應該將其從0開始列舉,即列舉重量從0開始直到cap,總共有cap+1個值,同理對於找零錢問題,只給定了一個最大值aim,但是在分解為題時應該從0開始直到aim考慮aim+1個值。
初始條件:
第一行的值,表示使用第一將物品w[0]來裝包,顯然當容量小於w[0]時無法裝入因此價值為0,之後可以裝入,於是最大價值顯然就是v[0]=4;
第一列的值,表示使用前i個物品來裝包,當容量為0時的最大價值,顯然一個都放不下,所以價值都為0。
對於任意的dp[i][j]2種情況:第i件物品放還是不放:
(1)如果i物品不裝入,dp[i-1][j];
(2)如果i物品裝入,物品i的重量為w[i],物品i的價值為v[i],那麼即是求在重量限制j-w[i]條件下的最大價值,即轉變為求dp[i-1][j-w[i]],求的dp[i-1][j-w[i]]後,此時的價值為dp[i-1][j-w[i]]+v[i]
即dp[i][j]=Math.max(dp[i-1][j];dp[i-1][j-w[i]]+v[i]);需要注意的是,在求dp[i-1][j-w[i]]時,對於有些j並不一定大於w[i],即j-w[i],此時表示無法裝入物品i,於是此時dp[i][j]應該直接等於dp[i-1][j];於是在求dp[i][j]時對j-w[i]進行一個if判斷然後使用Math.max判斷或者直接取dp[i-1][j]即可。
動態規劃4部曲:
①建立動態規劃二維陣列儲存答案dp[n][cap+1];
②計算第1行和第1列的元素值
第1行:從j=w[0]開始dp[0][j]=v[0];
第1列:dp[i][0]=0;
③從上到下,從左到右計算任意dp[i][j],根據[j-w[i]<0使用不同的計算邏輯
④返回結果,右下角的值dp[n-1][aim]就是所求的結果;
- import java.util.*;
- //01揹包問題:動態規劃4部曲
- public class Backpack {
- public int maxValue(int[] w, int[] v, int n, int cap) {
- //特殊輸入
- if(w==null||v==null||n<=0||cap<=0) return 0;
- //①建立動態規劃陣列存放答案dp[][]
- int[][] dp=new int[n][cap+1];
- //②計算dp[][]第1行值
- for(int i=w[0];i<=cap;i++){
- dp[0][i]=v[0];
- }
- //②計算dp[][]第1列的值:全是0,預設也是0,故無需操作
- //③從上到下,從左到右計算任意dp[i][j]
- for(int i=1;i<n;i++){
- for(int j=1;j<=cap;j++){
- if(j-w[i]>=0){
- dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
- }else{
- dp[i][j]=dp[i-1][j];
- }
- }
- }
- //④返回dp[][]右下角即為所求結果
- return dp[n-1][cap];
- }
- }
程式碼二:只使用1個陣列,
public class Backpack {
public int maxValue(int[] w, int[] v, int n, int cap) {
// dp[x][y]表示物品數量為x,重量不超過y時揹包中的總價值
//兩種情況:1.將x物品不加入到揹包中,那麼前x-1件物品的總重量不應該超過y。dp[x][y] = dp[x-1][y]
//2.將x物品加入到揹包中,那麼前x-1前物品的總重量不應該超過y-w(x),因此dp[x][y] = dp[x-1][y-w(x)]+v(x);
int[] dp = new int[cap+1];
for(int i=0;i<n;i++){//控制物品的數量
for(int j=cap;j>=w[i];j--){//空揹包中不能超重
dp[j] = dp[j]>=dp[j-w[i]]+v[i]?dp[j]:dp[j-w[i]]+v[i];//選取j加入書包與j不加入書包的較大值
}
}
return dp[cap];//返回陣列的最後一位即是最大總價值
}
}
- import java.util.*;
- public class Backpack {
- public int maxValue(int[] w, int[] v, int n, int cap) {
- // write code here
- int dp[] = new int[cap + 1];
- for(int i = 0; i < n; i++ ){
- for(int j = cap; j >= w[i]; j--){
- dp[j] = Math.max(dp[j], dp[j - w[i]] + v[i]);
- }
- }
- return dp[cap];
- }
- }
相關文章
- 0-1揹包問題(動態規劃)動態規劃
- 動態規劃解0-1揹包問題動態規劃
- 0-1揹包問題 動態規劃法動態規劃
- 動態規劃之 0-1 揹包問題詳解動態規劃
- 【動態規劃】0-1揹包問題原理和實現動態規劃
- 動態規劃-揹包類動態規劃
- 揹包問題----動態規劃動態規劃
- 【動態規劃】揹包問題動態規劃
- 動態規劃 01揹包問題動態規劃
- 【動態規劃】01揹包問題動態規劃
- 動態規劃-01揹包問題動態規劃
- 動態規劃篇——揹包問題動態規劃
- 動態規劃--01揹包問題動態規劃
- 【動態規劃】01揹包問題【續】動態規劃
- 演算法-動態規劃-完全揹包演算法動態規劃
- 01揹包動態規劃空間優化動態規劃優化
- 多重揹包動態規劃及空間優化動態規劃優化
- 動態規劃之0,1揹包問題動態規劃
- 動態規劃系列之六01揹包問題動態規劃
- 01揹包問題理解動態規劃演算法動態規劃演算法
- 動態規劃-揹包01問題推理與實踐動態規劃
- 【動態規劃】一次搞定三種揹包問題動態規劃
- 詳解動態規劃01揹包問題--JavaScript實現動態規劃JavaScript
- 詳解動態規劃01揹包問題–JavaScript實現動態規劃JavaScript
- 雙核處理(動態規劃的01揹包問題)動態規劃
- python 動態規劃(揹包問題和最長公共子串)Python動態規劃
- 動態規劃之01揹包問題(最易理解的講解)動態規劃
- DP 動態規劃 Problem V 1022 反向考慮的揹包動態規劃
- 【演算法】0-1揹包問題演算法
- 前端與演算法-動態規劃之01揹包問題淺析與實現前端演算法動態規劃
- 洛谷 1064——金明的預算方案(動態規劃的揹包問題)動態規劃
- 【動態規劃(一)】動態規劃基礎動態規劃
- 揹包問題演算法全解析:動態規劃和貪心演算法詳解演算法動態規劃
- [資料結構與演算法]-動態規劃之揹包演算法終極版資料結構演算法動態規劃
- 【演算法資料結構Java實現】Java實現動態規劃(揹包問題)演算法資料結構Java動態規劃
- leetcode題解(0-1揹包問題)LeetCode
- 【LeetCode動態規劃#08】完全揹包問題實戰與分析(零錢兌換II)LeetCode動態規劃
- 動態規劃動態規劃