蒜头君去超市购物,他有一只容量为 V 的购物袋,同时他买了 n件物品,已知每件物品的体积 vi。蒜头君想知道,挑选哪些物品放入购物袋中,可以使袋子剩余的空间最小。
输入格式
第一行输入一个整数 V(1≤V≤20,000),表示购物袋的容量。
第二行输入一个整数 n(1≤n≤30),表示蒜头君购买的n件物品。
接下来输入n行,每行输入一个整数 vi(1≤vi≤10,000),表示第i件物品的体积。
输出格式
输出一行,输出一个整数,表示购物袋最小的剩余空间。
样例输入
20 5 7 5 7 3 7
样例输出
1
动态规划中背包问题,几乎相当于没有改。
剩下的最小的空间 = V - 能装的最大的空间。
而且这题的每个物品的价值就相当于他的体积,都省的建两个数组了。
状态转移方程:f[i][j] = Math.max(f[i - 1][j], f[i - 1][j - p[i]] + p[i])
*f[i][j]表示在容量为 j 的情况下能装下的 i 个物品中的最大体积数
Java代码:
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int V = in.nextInt(), n = in.nextInt();
int[] p = new int[n + 1];
for(int i = 1; i <= n; i++) {
p[i] = in.nextInt();
}
in.close();
int[][] f = new int[n + 1][V + 1];
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= V; j++) {
if(p[i] <= j) {
f[i][j] = Math.max(f[i - 1][j], f[i - 1][j - p[i]] + p[i]);
}else {
f[i][j] = f[i - 1][j];
}
}
}
System.out.println(V - f[n][V]);
}
}
另附上标准01背包问题代码:
* v 和 p 分别为表示体积数组与表示价值数组
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int V = in.nextInt(), n = in.nextInt();
int[] v = new int[n + 1];
int[] p = new int[n + 1];
for(int i = 1; i <= n; i++) {
v[i] = in.nextInt();
p[i] = in.nextInt();
}
in.close();
int[][] f = new int[n + 1][V + 1];
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= V; j++) {
if(v[i] <= j) {
f[i][j] = Math.max(f[i - 1][j], f[i - 1][j - v[i]] + p[i]);
}else {
f[i][j] = f[i - 1][j];
}
}
}
System.out.println(f[n][V]);
}
}