首页 > 试题广场 >

购物单

[编程题]购物单
  • 热度指数:452546 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
王强决定把年终奖用于购物,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:
主件 附件
电脑 打印机,扫描仪
书柜 图书
书桌 台灯,文具
工作椅
如果要买归类为附件的物品,必须先买该附件所属的主件,且每件物品只能购买一次。
每个主件可以有 0 个、 1 个或 2 个附件。附件不再有从属于自己的附件。
王强查到了每件物品的价格(都是 10 元的整数倍),而他只有 N 元的预算。除此之外,他给每件物品规定了一个重要度,用整数 1 ~ 5 表示。他希望在花费不超过 N 元的前提下,使自己的满意度达到最大。
满意度是指所购买的每件物品的价格与重要度的乘积的总和,假设设第i件物品的价格为,重要度为,共选中了k件物品,编号依次为j_1,j_2,...,j_k,则满意度为:。(其中 * 为乘号)
请你帮助王强计算可获得的最大的满意度。




输入描述:
输入的第 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。


输出描述:
 输出一个正整数,为张强可以获得的最大的满意度。
示例1

输入

1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0

输出

2200
示例2

输入

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 });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void async function () {
    // Write your code here
    let inputs = []
    while(line = await readline()){
        inputs.push(line.split(' ').map(n=>parseInt(n)))
    }
    let n=0,m=0;
    let primary = {},annex = {}
    n = inputs[0][0]
    m = inputs[0][1]
    for(let i=1;i<m+1;i++){
        let x,y,z;
        [x,y,z] = inputs[i];
        if (z===0){
            // 主件
            primary[i]=[x,y]
        }else{
            // 附件
            if(annex[z]){
                // 已经有记录,添加附件,没有记录,新增附件列表
                annex[z].push([x,y])
            }else{
                annex[z] = [[x,y]]
            }
        }
    }

    m = Object.keys(primary).length; //数量转为主件数量
    dp = []
    for(let i=0;i<m+1;i++){
        let temp = []
        for(let j=0;j<n+1;j++){
            temp.push(0)
        }
        dp.push(temp)
    }

    let w = [[]], v= [[]]
    
    for(let key in primary){
        let w_temp=[], v_temp=[];
        w_temp.push(primary[key][0]); //主件价格
        v_temp.push(primary[key][0]*primary[key][1]) //满意度
        if (annex[key]){
            w_temp.push(w_temp[0]+annex[key][0][0])//主件+附件1
            v_temp.push(v_temp[0]+annex[key][0][0]*annex[key][0][1])
            if(annex[key].length===2){ 
            //2个附件
                w_temp.push(w_temp[0]+annex[key][1][0])//主件+附件2
                v_temp.push(v_temp[0]+annex[key][1][0]*annex[key][1][1])
                w_temp.push(w_temp[0]+annex[key][0][0]+annex[key][1][0])//主件+附件1+附件2
                v_temp.push(v_temp[0]+annex[key][0][0]*annex[key][0][1]+annex[key][1][0]*annex[key][1][1])
            }
        }
        w.push(w_temp);
        v.push(v_temp);
    }
    for (let i=1;i<m+1;i++){
        for(let j=10;j<n+1;j+=10){
            let max_i = dp[i-1][j]
            for(let k=0;k<w[i].length;k++){
                if(j-w[i][k]>=0){
                    max_i=Math.max(max_i,dp[i-1][j-w[i][k]]+v[i][k])
                }
            }
            dp[i][j]=max_i
        }
    }
    console.log(dp[m][n])
}()
https://blog.nowcoder.net/n/82b5f014a8654c8b8dbff4fe4fa727bd?f=comment  抄来的
发表于 2023-11-18 23:09:28 回复(0)
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
    // Write your code here
    let line1 = await readline();
    let tokens = line1.split(" ");
    let N = (parseInt(tokens[0]) / 10) | 0;
    let m = parseInt(tokens[1]);
    const items = [];
    const map = new Map();
    let id = 1;
    while ((line = await readline())) {
        let tokens = line.split(" ");
        let v = parseInt(tokens[0]) / 10;
        let p = parseInt(tokens[1]);
        let q = parseInt(tokens[2]);
        const item = { id, v, p, q, value: v * p };
        if (item.q === 0) {
            item.children = [];
        }
        items.push(item);
        map.set(id, item);
        id++;
    }
    for (let i = 0; i < items.length; i++) {
        let item = items[i];
        if (item.q !== 0) {
            map.get(item.q).children.push(item);
        }
    }
    const pItems = items.filter((item) => item.q === 0);
    let dp = new Array(pItems.length + 1)
        .fill()
        .map(() => new Array(N + 1).fill(0));
    const getDp = (i, j) => {
        if (i < 0 || j < 0) {
            return;
        }
    };
    for (let i = 1; i <= pItems.length; i++) {
        for (let j = 1; j <= N; j++) {
            const item = pItems[i - 1];
            const childNum = item.children.length;
            if (j >= item.v) {
                dp[i][j] = Math.max(
                    dp[i - 1][j],
                    dp[i - 1][j - item.v] + item.value
                );
                if (childNum === 1) {
                    let childItem = item.children[0];
                    if (j - item.v - childItem.v >= 0) {
                        dp[i][j] = Math.max(
                            dp[i][j],
                            dp[i - 1][j - item.v - childItem.v] +
                                item.value +
                                childItem.value
                        );
                    }
                } else {
                    if (childNum === 2) {
                        let childItem1 = item.children[0];
                        let childItem2 = item.children[1];
                        if (j - item.v - childItem1.v >= 0) {
                            dp[i][j] = Math.max(
                                dp[i][j],
                                dp[i - 1][j - item.v - childItem1.v] +
                                    item.value +
                                    childItem1.value
                            );
                        }
                        if (j - item.v - childItem2.v >= 0) {
                            dp[i][j] = Math.max(
                                dp[i][j],
                                dp[i - 1][j - item.v - childItem2.v] +
                                    item.value +
                                    childItem2.value
                            );
                        }
                        if (j - item.v - childItem1.v-childItem2.v >= 0) {
                            dp[i][j] = Math.max(
                                dp[i][j],
                                dp[i - 1][
                                    j - item.v - childItem1.v - childItem2.v
                                ] +
                                    item.value +
                                    childItem1.value +
                                    childItem2.value
                            );
                        }
                    }
                }
            } else {
                dp[i][j] = dp[i - 1][j];
            }
        }
    }
    console.log(dp[pItems.length][N] * 10);
})();

发表于 2023-09-02 12:18:07 回复(0)
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
    // Write your code here
    //1. 读取数据
    let token = [];
    while ((line = await readline())) {
        let tokens = line.split(" ");
        token.push(tokens.map(Number));
    }
    let [N, m] = token[0];
    let V = [0],
        W = [0],
        R = [0];
    let temp;
    for (let i = 1; i < token.length; i++) {
        V.push(token[i][0]);
        W.push(token[i][1]);
        R.push(token[i][2]);
    }

    //2. 分段
    //求最大公因数
    function gcd(a, b) {
        if (b == 0) {
            return a;
        }
        var r = a % b;
        return gcd(b, r);
    }
    //求一组数的最大公因数
    let gap = V.concat(N).reduce((prev, curr) => gcd(prev, curr));
    //统一单位大小
    V = V.map((v) => v / gap);
    //dp表
    let containerLength = N / gap;
    let container = new Array(containerLength + 1).fill(0);

    let inCart = new Array(containerLength + 1).fill(new Array(1).fill(0));
    for (let i = 1; i < m + 1; i++) {
        //前i个物体
        for (let j = containerLength; j >= V[i]; j--) {
            //容量为j
            let curr = j,
                before = j - V[i];
            let wealth,
                currValue,
                prevValue = container[curr];
            let [mainItemValue, mainItemWeight] = [V[R[i]], W[R[i]]];
            //       console.log(i,container);
            //       console.log(inCart[curr]);
            if (!inCart[before].includes(i)) {
                //没有重复当前的这个物件
                if (inCart[before].includes(R[i])) {
                    //如果主件已入购物车
                    wealth = V[i] * W[i];
                    currValue = container[j - V[i]] + wealth;
                    if (currValue > prevValue) {
                        container[j] = currValue;
                        inCart[curr] = inCart[before].concat([i]);
                    }
                } else if (j - mainItemValue - V[i] >= 0) {
                    //如果主件没进,那么考虑把主件也并在一起
                    wealth = mainItemValue * mainItemWeight + V[i] * W[i];
                    currValue = container[j - mainItemValue - V[i]] + wealth;
                    if (
                        !inCart[j - mainItemValue - V[i]].includes(i) &&
                        //                      !inCart[j-mainItemValue-V[i]].includes(R[i])  &&
                        currValue > prevValue
                    ) {
                        container[j] = currValue;
                        inCart[curr] = inCart[j - mainItemValue - V[i]].concat([
                            i,
                            R[i],
                        ]);
                    }
                }
            }
        }
    }
    console.log(container[containerLength] * gap);
})();

发表于 2023-06-17 16:48:46 回复(0)
这些题目这么抽象的吗
发表于 2023-03-23 16:36:03 回复(3)