动态规划背包问题4混合背包

动态规划背包问题4混合背包

四月 11, 2020

混合背包问题


有 N 种物品和一个容量是 V 的背包。

物品一共有三类:

第一类物品只能用1次(01背包);
第二类物品可以用无限次(完全背包);
第三类物品最多只能用 si 次(多重背包);
每种体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。

输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。

接下来有 N 行,每行三个整数 vi,wi,si,用空格隔开,分别表示第 i 种物品的体积、价值和数量。

si=−1 表示第 i 种物品只能用1次;
si=0 表示第 i 种物品可以用无限次;
si>0 表示第 i 种物品可以使用 si 次;
输出格式
输出一个整数,表示最大价值。

数据范围
0<N,V≤1000
0<vi,wi≤1000
−1≤si≤1000


来源acwing

对于每一种情况,有不同的解决方式,如果再把多重背包给拆分,那么就只剩两种情况。沿用了上一题的代码。

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
55
56
57
58
59
60
61
62
63
64
65
66
67
import java.util.*;

public class Main {
public static int solve(int N,int V,int[] v,int[] w,int[] s,ArrayList<Integer> listv,ArrayList<Integer> listw) {
int[] dp = new int[V + 1];
for (int i = 0; i < listv.size(); i++) {
if (listw.get(i) < 0) {
//如果是完全背包,无限个的话存储用负数
for (int j = 0; j <= V; j++) {
if (j >= listv.get(i))
dp[j] = Math.max(dp[j], dp[j - listv.get(i)] - listw.get(i));
}
}
else {
for (int j = V; j >= listv.get(i); j--) {
dp[j] = Math.max(dp[j],dp[j - listv.get(i)] + listw.get(i));

}
}
//show(dp);
}


return dp[dp.length - 1];

}
public static void show(int[] arr) {
for (int i = 0; i <arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println("*");
}
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];
int[] s = new int[N + 1];
ArrayList<Integer> listv = new ArrayList<>(1001);
ArrayList<Integer> listw = new ArrayList<>(1001);
for (int i = 1; i <= N; i++) {
v[i] = sc.nextInt();
w[i] = sc.nextInt();
s[i] = sc.nextInt();
//这里这些数组也没用了,下面根据背包的情况来存储值
if (s[i] > 0) {
for (int j = 1; j <= s[i]; j *= 2) {
s[i] -= j;
listv.add(v[i] * j);
listw.add(w[i] * j);
}
if (s[i] > 0) {
listv.add(v[i] * s[i]);
listw.add(w[i] * s[i]);
}
} else {
int p = 1;
if (s[i] == 0) p = -1;
listv.add(v[i]);
listw.add(w[i]* p);
}

}
System.out.println(solve(N,V,v,w,s,listv,listw));
}
}

把前面的三种背包弄明白,其实主要是01和完全背包,因为多重背包就是01,这道题很好写。