题解 | 华为题库-购物单-01背包
购物单
https://www.nowcoder.com/practice/f9c6f980eeec43ef85be20755ddbeaf4
题型:01背包变形
解题思路:
- 一个物品只能选一次,因此是01背包
- 但本题有附加条件:选择了主件才能选择附件
- 对每个主件,求出与其的附件搭配,将搭配后的主件看作“物品”,分别有四种情况,得到搭配后的价格与重要度 price[]、weight[]
- 主件
- 主件加附件1
- 主件加附件2
- 主件加附件1加附件2
- 先遍历物品,再遍历容量,由于是「一维」「01」背包,为了防止物品多次加入背包,遍历容量要倒序
- 尝试将搭配后的物品加入背包
- dp[j] = Math.max(dp[j], dp[j - price[k]] + weight[k]);
附一维背包总结规律
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();// 容量
int m = sc.nextInt();// 物品
if (N <= 0 || m <= 0) {
System.out.println(0);
return;
}
Good[] goods = new Good[m + 1];
for (int i = 1; i <= m; i++) {
goods[i] = new Good();
}
for (int i = 1; i <= m; i++) {
goods[i].price = sc.nextInt();// 价格
goods[i].weight = sc.nextInt();// 重要度
int owner = sc.nextInt();// 主件
goods[i].owner = owner;
if (owner > 0) {
if (goods[owner].a1 == 0) {
goods[owner].a1 = i;
} else {
goods[owner].a2 = i;
}
}
}
int[] dp = new int[N + 1];
// 先遍历物品
for (int i = 1; i <= m; i++) {
if (goods[i].owner > 0) { //当物品i是附件时,跳过
continue;
}
int price[] = new int[4], weight[] = new int[4];
//只有主件
price[0] = goods[i].price;
weight[0] = goods[i].price * goods[i].weight;
//主件加附件1
if (goods[i].a1 != 0) {
price[1] = price[0] + goods[goods[i].a1].price;
weight[1] = weight[0] + goods[goods[i].a1].price * goods[goods[i].a1].weight;
}
//主件加附件2
if (goods[i].a2 != 0) {
price[2] = price[0] + goods[goods[i].a2].price;
weight[2] = weight[0] + goods[goods[i].a2].price * goods[goods[i].a2].weight;
}
//主件加附件1和附件2
if (goods[i].a1 != 0 && goods[i].a2 != 0) {
price[3] = price[0] + goods[goods[i].a1].price + goods[goods[i].a2].price;
weight[3] = weight[0] + goods[goods[i].a1].price * goods[goods[i].a1].weight
+ goods[goods[i].a2].price * goods[goods[i].a2].weight;
}
// 倒序遍历容量
for (int j = N; j >= 1; j--) {
for (int k = 0; k < 4; k++) {
// 能装下这件物品
if (j >= price[k] && price[k] != 0) {
dp[j] = Math.max(dp[j], dp[j - price[k]] + weight[k]);
}
}
}
}
System.out.println(dp[N]);
}
/**
* 定义物品类
*/
private static class Good {
public int price; //物品的价格
public int weight; //物品的重要度
public int owner; //物品的主件ID
public int a1 = 0; //附件1ID
public int a2 = 0; //附件2ID
}
}

