有 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]; } }