gyro永不抽风

ああああああああああああああああおおおおおおおおおおおおおおおお

P1064 金明的预算方案 - 背包问题

题目

题目描述

金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过 nn 元钱就行”。今天一早,金明就开始做预算了,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:

主件 附件
电脑 打印机,扫描仪
书柜 图书
书桌 台灯,文具
工作椅

如果要买归类为附件的物品,必须先买该附件所属的主件。每个主件可以有 00 个、11 个或 22 个附件。每个附件对应一个主件,附件不再有从属于自己的附件。金明想买的东西很多,肯定会超过妈妈限定的 nn 元。于是,他把每件物品规定了一个重要度,分为 55 等:用整数 151 \sim 5 表示,第 55 等最重要。他还从因特网上查到了每件物品的价格(都是 1010 元的整数倍)。他希望在不超过 nn 元的前提下,使每件物品的价格与重要度的乘积的总和最大。

设第 jj 件物品的价格为 vjv_j,重要度为wjw_j,共选中了 kk 件物品,编号依次为 j1,j2,,jkj_1,j_2,\dots,j_k,则所求的总和为:

vj1×wj1+vj2×wj2++vjk×wjkv_{j_1} \times w_{j_1}+v_{j_2} \times w_{j_2}+ \dots +v_{j_k} \times w_{j_k}

请你帮助金明设计一个满足要求的购物单。

输入格式

第一行有两个整数,分别表示总钱数 nn 和希望购买的物品个数 mm

22 到第 (m+1)(m + 1) 行,每行三个整数,第 (i+1)(i + 1) 行的整数 viv_ipip_iqiq_i 分别表示第 ii 件物品的价格、重要度以及它对应的的主件。如果 qi=0q_i=0,表示该物品本身是主件。

输出格式

输出一行一个整数表示答案。

输入输出样例

输入 #1
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0
输出 #1
2200

说明/提示

数据规模与约定

对于全部的测试点,保证 1n3.2×1041 \leq n \leq 3.2 \times 10^41m601 \leq m \leq 600vi1040 \leq v_i \leq 10^41pi51 \leq p_i \leq 50qim0 \leq q_i \leq m,答案不超过 2×1052 \times 10^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;
}
__EOF__
-------------本文结束感谢您的阅读-------------

本文标题:P1064 金明的预算方案 - 背包问题

文章作者:gyro永不抽风

发布时间:2020年09月24日 - 12:09

最后更新:2020年09月24日 - 17:09

原始链接:http://gyrojeff.moe/2020/09/24/P1064-%E9%87%91%E6%98%8E%E7%9A%84%E9%A2%84%E7%AE%97%E6%96%B9%E6%A1%88-%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98/

许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 转载请保留原文链接及作者!

真的不买杯奶茶吗?T^T

欢迎关注我的其它发布渠道