王强决定把年终奖用于购物,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:
| 主件 | 附件 |
| 电脑 | 打印机,扫描仪 |
| 书柜 | 图书 |
| 书桌 | 台灯,文具 |
| 工作椅 | 无 |
如果要买归类为附件的物品,必须先买该附件所属的主件,且每件物品只能购买一次。
每个主件可以有 0 个、 1 个或 2 个附件。附件不再有从属于自己的附件。
王强查到了每件物品的价格(都是 10 元的整数倍),而他只有 N 元的预算。除此之外,他给每件物品规定了一个重要度,用整数 1 ~ 5 表示。他希望在花费不超过 N 元的前提下,使自己的满意度达到最大。
满意度是指所购买的每件物品的价格与重要度的乘积的总和,假设设第ii件物品的价格为v[i]v[i],重要度为w[i]w[i],共选中了kk件物品,编号依次为j1,j2,...,jkj1,j2,...,jk,则满意度为:v[j1]∗w[j1]+v[j2]∗w[j2]+…+v[jk]∗w[jk]v[j1]∗w[j1]+v[j2]∗w[j2]+…+v[jk]∗w[jk]。(其中 * 为乘号)
请你帮助王强计算可获得的最大的满意度。
输入描述:
输入的第 1 行,为两个正整数N,m,用一个空格隔开。其中 N 表示总钱数, m 为可购买的物品的个数。
从第 2 行到第 m+1 行,第 j 行给出了编号为 j-1 的物品的基本数据,每行有 3 个非负整数 v、p、q。
其中 v 表示该物品的价格,p 表示该物品的重要度,q 表示该物品是主件还是附件。
如果 q=0,表示该物品为主件,如果q>0,表示该物品为附件, q 是所属主件的编号。
数据范围:N<32000,m<60,v<10000,1<=p<=5。
输出描述:
输出一个正整数,为张强可以获得的最大的满意度。
输入:
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0
输出:
2200
输入:
50 5
20 3 5
20 3 5
10 3 0
10 2 0
10 1 0
输出:
130
说明:
由第1行可知总钱数N为50以及希望购买的物品个数m为5;
第2和第3行的q为5,说明它们都是编号为5的物品的附件;
第4~6行的q都为0,说明它们都是主件,它们的编号依次为3~5;
所以物品的价格与重要度乘积的总和的最大值为10*1+20*3+20*3=130
const rl = require("readline").createInterface({
input: process.stdin,
output: process.stdout,
});
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void (async function () {
// 读取 n 和 m 的值
const line1 = await readline();
let [n, m] = line1.split(" ").map(Number);
// 初始化主件和附件价格和重要性数组,主件索引为0,附件索引为1和2,长度为3
let price = new Array(m + 1).fill(0).map(() => new Array(3).fill(0));
let importance = new Array(m + 1).fill(0).map(() => new Array(3).fill(0));
// 读取物品的价值、价格和类型
for (let i = 1; i <= m; i++) {
const line = await readline();
// v: 价格, p: 重要性, q: 类型
let [v, p, q] = line.split(" ").map(Number);
// 计算重要性
let im = v * p;
// 类型为 0 时,说明类型为主件,没有附件的情况
if (q === 0) {
price[i][0] = v;
importance[i][0] = im;
} else {
// 类型不为 0 时,说明类型为附件
if (price[q][1] === 0) {
// 计算主件编号对应的第一个附件的价格和重要性
price[q][1] = v;
importance[q][1] = im;
} else {
// 计算主件编号对应的第二个附件的价格和重要性
price[q][2] = v;
importance[q][2] = im;
}
}
}
// 初始化动态规划数组,dp[i] 表示现在剩余可用金钱为 i 时的最大价值
let dp = new Array(n + 1).fill(0);
// 动态规划计算最大价值
for (let i = 1; i <= m; i++) {
if (price[i][0] === 0) continue;
for (let j = n; j >= price[i][0]; j--) {
// a: 当前主件价格, a1: 主件重要性
let a = price[i][0];
let a1 = importance[i][0];
// b: 当前主件价格对应的附件价格, b1: 当前主件价格对应的附件重要性
let b = price[i][1];
let b1 = importance[i][1];
// c: 当前主件价格对应的附件价格, c1: 当前主件价格对应的附件重要性
let c = price[i][2];
let c1 = importance[i][2];
// 动态规划计算,计算当前金钱下的最大价值,比较主件,主件+附件1,主件+附件2,主件+附件1+附件2的情况
// 如果当前金钱大于主件价格,取最大值
if (j >= a) {
dp[j] = Math.max(dp[j], dp[j - a] + a1);
}
// 如果当前金钱大于主件和附件1的价格,取最大值
if (j >= a + b) {
dp[j] = Math.max(dp[j], dp[j - a - b] + a1 + b1);
}
// 如果当前金钱大于主件和附件2的价格,取最大值
if (j >= a + c) {
dp[j] = Math.max(dp[j], dp[j - a - c] + a1 + c1);
}
// 如果当前金钱大于主件和附件1和附件2的价格,取最大值
if (j >= a + b + c) {
dp[j] = Math.max(dp[j], dp[j - a - b - c] + a1 + b1 + c1);
}
}
}
// 输出最大价值
console.log(dp[n]);
})();
490

被折叠的 条评论
为什么被折叠?



