题解 | 华为题库-购物单-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 } }