题目 题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过 n n n 元钱就行”。今天一早,金明就开始做预算了,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:
主件
附件
电脑
打印机,扫描仪
书柜
图书
书桌
台灯,文具
工作椅
无
如果要买归类为附件的物品,必须先买该附件所属的主件。每个主件可以有 0 0 0 个、1 1 1 个或 2 2 2 个附件。每个附件对应一个主件,附件不再有从属于自己的附件。金明想买的东西很多,肯定会超过妈妈限定的 n n n 元。于是,他把每件物品规定了一个重要度,分为 5 5 5 等:用整数 1 ∼ 5 1 \sim 5 1 ∼ 5 表示,第 5 5 5 等最重要。他还从因特网上查到了每件物品的价格(都是 10 10 1 0 元的整数倍)。他希望在不超过 n n n 元的前提下,使每件物品的价格与重要度的乘积的总和最大。
设第 j j j 件物品的价格为 v j v_j v j ,重要度为w j w_j w j ,共选中了 k k k 件物品,编号依次为 j 1 , j 2 , … , j k j_1,j_2,\dots,j_k j 1 , j 2 , … , j k ,则所求的总和为:
v j 1 × w j 1 + v j 2 × w j 2 + ⋯ + v j k × w j k v_{j_1} \times w_{j_1}+v_{j_2} \times w_{j_2}+ \dots +v_{j_k} \times w_{j_k} v j 1 × w j 1 + v j 2 × w j 2 + ⋯ + v j k × w j k 。
请你帮助金明设计一个满足要求的购物单。
输入格式 第一行有两个整数,分别表示总钱数 n n n 和希望购买的物品个数 m m m 。
第 2 2 2 到第 ( m + 1 ) (m + 1) ( m + 1 ) 行,每行三个整数,第 ( i + 1 ) (i + 1) ( i + 1 ) 行的整数 v i v_i v i ,p i p_i p i ,q i q_i q i 分别表示第 i i i 件物品的价格、重要度以及它对应的的主件。如果 q i = 0 q_i=0 q i = 0 ,表示该物品本身是主件。
输出格式 输入输出样例 说明/提示 数据规模与约定
对于全部的测试点,保证 1 ≤ n ≤ 3.2 × 1 0 4 1 \leq n \leq 3.2 \times 10^4 1 ≤ n ≤ 3 . 2 × 1 0 4 ,1 ≤ m ≤ 60 1 \leq m \leq 60 1 ≤ m ≤ 6 0 ,0 ≤ v i ≤ 1 0 4 0 \leq v_i \leq 10^4 0 ≤ v i ≤ 1 0 4 ,1 ≤ p i ≤ 5 1 \leq p_i \leq 5 1 ≤ p i ≤ 5 ,0 ≤ q i ≤ m 0 \leq q_i \leq m 0 ≤ q i ≤ m ,答案不超过 2 × 1 0 5 2 \times 10^5 2 × 1 0 5 。
题解 这道题可以只枚举主要物品,有五种选择方法:
主
主 + 副1
主 + 副2
主 + 副1 + 副2
不选
然后其实就是普通的背包问题了(撒花
代码 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 #include <iostream> using namespace std ;const int maxm = 65 ;const int maxn = 32005 ;int pos[maxm], cnt[maxm], f[maxn];struct node { int v, p; } a[maxm][3 ];int main () { int n, m, k = 0 ; cin >> n >> m; for (int i = 1 ; i <= m; i ++) { int v, p, q; cin >> v >> p >> q; if (q == 0 ) { a[++ k][0 ] = (node) { v, p }; pos[i] = k; } else a[pos[q]][++ cnt[q]] = (node) { v, p }; } for (int i = 1 ; i <= k; i ++) { for (int j = n; j >= a[i][0 ].v; j --) { if (j >= a[i][0 ].v + a[i][1 ].v + a[i][2 ].v) f[j] = max(f[j], f[j - (a[i][0 ].v + a[i][1 ].v + a[i][2 ].v)] + a[i][0 ].v * a[i][0 ].p + a[i][1 ].v * a[i][1 ].p + a[i][2 ].v * a[i][2 ].p); if (j >= a[i][0 ].v + a[i][1 ].v) f[j] = max(f[j], f[j - (a[i][0 ].v + a[i][1 ].v)] + a[i][0 ].v * a[i][0 ].p + a[i][1 ].v * a[i][1 ].p); if (j >= a[i][0 ].v + a[i][2 ].v) f[j] = max(f[j], f[j - (a[i][0 ].v + a[i][2 ].v)] + a[i][0 ].v * a[i][0 ].p + a[i][2 ].v * a[i][2 ].p); if (j >= a[i][0 ].v) f[j] = max(f[j], f[j - a[i][0 ].v] + a[i][0 ].v * a[i][0 ].p); } } cout << f[n] << endl ; return 0 ; }