有乙個容量為 n 的揹包,要用這個揹包裝下物品的價值最大,這些物品有兩個屬性:體積 w 和價值 v。
定義乙個二維陣列 dp 儲存最大價值,其中 dp[i][j] 表示前 i 件物品體積不超過 j 的情況下能達到的最大價值。設第 i 件物品體積為 w,價值為 v,根據第 i 件物品是否新增到揹包中,可以分兩種情況討論:
第 i 件物品可新增也可以不新增,取決於哪種情況下最大價值更大。因此,0-1 揹包的狀態轉移方程為:
// w 為揹包總體積
// n 為物品數量
// weights 陣列儲存 n 個物品的重量
// values 陣列儲存 n 個物品的價值
public
intknapsack
(int w,
int n,
int[
] weights,
int[
] values)
else}}
return dp[n]
[w];
}
在程式實現時可以對 0-1 揹包做優化。觀察狀態轉移方程可以知道,前 i 件物品的狀態僅與前 i-1 件物品的狀態有關,因此可以將 dp 定義為一維陣列,其中 dp[j] 既可以表示 dp[i-1][j] 也可以表示 dp[i][j]。此時,
因為 dp[j-w] 表示 dp[i-1][j-w],因此不能先求 dp[i][j-w],防止將 dp[i-1][j-w] 覆蓋。也就是說要**先計算 dp[i][j] 再計算 dp[i][j-w],**在程式實現時需要按倒序來迴圈求解。
j是從w降到 1 ,而不是從1公升到w,特別注意!!!
public
intknapsack
(int w,
int n,
int[
] weights,
int[
] values)
/* j}
}return dp[w]
;}
leetcode題:將陣列劃分為相等兩部分
可以看成乙個揹包大小為 sum/2 的 0-1 揹包問題。
class
solution
if(sum %2!=
0)return
false
;int w= sum /2;
//0-1揹包問題
boolean
dp =
newboolean
[w+1];
dp[0]
=true
;//注意,
for(
int i =
1;i<=n;i++)}
}return dp[w];}
}
(1)迴圈還可以改進:
將i = 1 ~n , 改為for(int i :nums)
//0-1揹包問題
boolean
dp =
newboolean
[w+1];
dp[0]
=true
;//注意,
for(
int i :nums)}}
return dp[w]
;
(2)還可以再改進??由上迴圈可發現,j boolean
dp =
newboolean
[w+1];
dp[0]
=true
;//注意,
for(
int i :nums)
}return dp[w]
;
動態規劃揹包問題 01揹包
問題描述 n種物品,每種乙個。第i種物品的體積為vi,重量為wi。選一些物品裝到容量為c的揹包,使得揹包內物品不超過c的前提下,重量最大。問題分析 宣告乙個f n c 的陣列。f i j 表示把前i件物品都裝到容量為j的揹包所獲得的最大重量。當 j v i 時,揹包容量不足以放下第 i 件物品,f ...
動態規劃 揹包問題 01揹包
有n種物品和乙個容量為v的揹包,每種物品僅用一次。第i件物品的費用是w i 價值是v i 求解將哪些物品裝入揹包可使價值總和最大。例如 n 5,v 10 重量 價值 第乙個物品 10 5 第二個物品 1 4 第三個物品 2 3 第四個物品 3 2 第五個物品 4 1 首先我們考慮貪心策略,選取最大價...
0 1揹包問題(動態規劃)
一 問題描述 有n件物品和乙個容量為v的揹包。第i件物品的費用是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。所謂01揹包,表示每乙個物品只有乙個,要麼裝入,要麼不裝入。二 解決方案 考慮使用動態規劃求解,定義乙個遞迴式 opt i v 表示前i個物品,在揹包容量大小為v的情況下,最...