蓝桥杯 ALGO-21算法训练 装箱问题 java版

问题描述

有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数)。 要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

输入格式

  第一行为一个整数,表示箱子容量; 第二行为一个整数,表示有n个物品; 接下来n行,每行一个整数表示这n个物品的各自体积。

输出格式

  一个整数,表示箱子剩余空间。

样例输入

24 6 8 3 12 7 9 7

样例输出

0

这是一个背包问题,用动态规划来解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import java.util.Scanner;

public class Main {

private static int[][] dpOne;
private static int[] dpTwo;

public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int V = in.nextInt();
int n = in.nextInt();
dpOne = new int[n + 1][V + 1];
int[] v = new int[n + 1];
for (int i = 1; i <= n; i++) {
v[i] = in.nextInt();
}
in.close();
MethodOne(n, v, V);
System.out.println(V - dpOne[n][V]);
dpTwo = new int[V + 1];
MethodTwo(n, v, V);
System.out.println(V - dpTwo[V]);
}

/*
* 用二维数组来存储 前n个物品放入体积为V的背包中,对于每个物品,如果不取,dp[i][j] = dp[i -
* 1][j]即前n-1个物品来装体积为V的这个背包 如果取,dp[i][j] = dp[i - 1][j - v[i]] + v[i]即前n
* -1个物品来装体积为V - v[i]的这个背包
*/
private static void MethodOne(int n, int[] v, int V) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= V; j++) {
if (j >= v[i]) {
dpOne[i][j] = Integer.max(dpOne[i - 1][j], dpOne[i - 1][j - v[i]] + v[i]);
} else {
dpOne[i][j] = dpOne[i - 1][j];
}
}
}
}

/*
* 用一维数组来存储 对于每个物品都有取和不取两个状态,如果不取,dp[j]不变,如果取dp[j] = dp[j - v[i]] + v[i]
*/
private static void MethodTwo(int n, int[] v, int V) {
for (int i = 1; i <= n; i++) {
for (int j = V; j > 0; j--) {
if (j >= v[i]) {
dpTwo[j] = Integer.max(dpTwo[j], dpTwo[j - v[i]] + v[i]);
}
}
}
}
}