有 N 件物品和一個容量是 V 的揹包。每件物品只能使用一次。java
第 i 件物品的體積是 vi,價值是 wi。code
求解將哪些物品裝入揹包,可以使這些物品的整體積不超過揹包容量,且總價值最大。
輸出最大價值。class
輸入格式
第一行兩個整數,N,V,用空格隔開,分別表示物品數量和揹包容積。import
接下來有 N 行,每行兩個整數 vi,wi,用空格隔開,分別表示第 i 件物品的體積和價值。遍歷
輸出格式
輸出一個整數,表示最大價值。im
數據範圍
0<N,V≤1000
0<vi,wi≤1000
輸入樣例
4 5
1 2
2 4
3 4
4 5
輸出樣例:
8next
經典動態規劃題
物品個數n,揹包總容量v
c[]表明每一個物品體積,w[]表明每一個物品價值
設f[i][j],表示前i件物品放入容量爲j的揹包的最大價值
所以可遍歷物品,並計算假設容量爲j時候的最大值。
此時有兩種狀況:
1.容量不夠(j < c[i]),則取不了當前物品,直接f[i][j]=f[i-1][j]
2.容量夠,則須要判斷取與不取當前物品的價值
若不取第i件,問題轉化爲求前i-1件物品放入容量爲v的揹包的問題,即f[i][j]=f[i-1][j]
若取第i件,問題轉化爲求前i-1件物品放入容量爲j-c[i]的揹包的問題,即f[i][j]=f[i-1][j-c[i]]+w[i]
因此f[i][j]便是求以上兩種狀況的最大值,最終狀態轉移方程是 f[i][v] = max(f[i-1][v], f[i-1][j-c[i]] + w[i])
最後答案就是f[n][v]數據
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt(); int V = sc.nextInt(); int[] v = new int[N + 1]; int[] w = new int[N + 1]; for(int i=1; i<=N; i++) { v[i] = sc.nextInt(); w[i] = sc.nextInt(); } System.out.println(cal(N, V, w, v)); } /** * 求01揹包的解 * @param n 物品個數 * @param v 揹包總容量 * @param w 每一個物品的價值,注意下標從1開始 * @param c 每一個物品的體積,注意下標從1開始 * @return */ private static int cal(int n, int v, int[] w, int[] c) { /* */ if (n == 0 || v == 0) return 0; if (w == null || w.length == 0) return 0; if (c == null || c.length == 0) return 0; int[][] f = new int[n + 1][v + 1]; for(int i=1; i<=n; i++) { for(int j=1;j<=v;j++) { f[i][j] = j<c[i]? f[i-1][j] : Math.max(f[i-1][j], f[i-1][j-c[i]] + w[i]); } } return f[n][v]; } }