题解 | #购物单# 01背包扩展,可读性强解法

购物单

https://www.nowcoder.com/practice/f9c6f980eeec43ef85be20755ddbeaf4

  • 核心: dp[i] = max(dp[i], dp[i-主件], dp[i-主件-附件1], dp[i-主件-附件2], dp[i-主件-附件1-附件2])
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static class Item {
        int id;
        int mainId; // 附件才有
        int p;
        int v; // p * itemValue
        Item sub1;
        Item sub2;
    }

    // 每个主件可以有 0 个、 1 个或 2 个附件!!
    // items.size() < 60
    // limitMoney < 32000
    // dp[i] = max(dp[i], dp[i-主件], dp[i-主件-附件1], dp[i-主件-附件2], dp[i-主件-附件1-附件2])
    static int getMaxSatisfyValue(Map<Integer, Item> items, int limitMoney) {
        int[] dp = new int[limitMoney + 1];
        for (Item item : items.values()) {
            for (int i = limitMoney; i >= item.p;
                    i--) { // 尝试买当前物品, 倒着防重复
                dp[i] = Math.max(dp[i], dp[i - item.p] + item.v);
                if (item.sub1 != null) {
                    int idx = i - item.p - item.sub1.p;
                    if (idx >= 0) {
                        dp[i] = Math.max(dp[i], dp[idx] + item.v + item.sub1.v);
                    }
                }
                if (item.sub2 != null) {
                    int idx = i - item.p - item.sub2.p;
                    if (idx >= 0) {
                        dp[i] = Math.max(dp[i], dp[idx] + item.v + item.sub2.v);
                    }
                }
                if (item.sub1 != null && item.sub2 != null) {
                    int idx = i - item.p - item.sub1.p - item.sub2.p;
                    if (idx >= 0) {
                        dp[i] = Math.max(dp[i], dp[idx] + item.v + item.sub1.v + item.sub2.v);
                    }
                }
            }
        }
        return dp[limitMoney];
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int limitMoney = in.nextInt();
        int itemCount = in.nextInt();
        List<Item> itemList = new ArrayList<>(itemCount);
        Map<Integer, Item> items = new HashMap<>();
        for (int id = 1; id <= itemCount; id++) {
            int p = in.nextInt();
            int value = in.nextInt();
            int mainId = in.nextInt();
            Item item = new Item();
            item.id = id;
            item.mainId = mainId;
            item.p = p;
            item.v = value * p;
            itemList.add(item);
            if (mainId == 0) {
                items.put(item.id, item);
            }
        }
        for (Item item : itemList) {
            if (item.mainId > 0) {
                Item mainItem = items.get(item.mainId);
                if (mainItem.sub1 == null) {
                    mainItem.sub1 = item;
                } else {
                    mainItem.sub2 = item;
                }
            }
        }
        int res = getMaxSatisfyValue(items, limitMoney);
        System.out.println(res);
    }
}
#经典01背包问题稍作修改就可以得出这题的解答#
全部评论

相关推荐

06-27 12:54
已编辑
门头沟学院 Java
累了,讲讲我的大学经历吧,目前在家待业。我是一个二本院校软件工程专业。最开始选专业是觉得计算机感兴趣,所以选择了他。本人学习计算机是从大二暑假结束开始的,也就是大三开始。当时每天学习,我个人认为Java以及是我生活的一部分了,就这样持续学习了一年半,来到了大四上学期末,大概是在12月中旬,我终于找的到了一家上海中厂的实习,但我发现实习生的工作很枯燥,公司分配的活也不多,大多时间也是自己在自学。就这样我秋招末才找到实习。时间来到了3月中旬,公司说我可以转正,但是转正工资只有7000,不过很稳定,不加班,双休,因为要回学校参加答辩了,同时当时也是心高气傲,认为可以找到更好的,所以放弃了转正机会,回学校准备论文。准备论文期间就也没有投递简历。然后时间来到了5月中旬,这时春招基本也结束了,然后我开始投递简历,期间只是约到了几家下场面试。工资也只有6-7k,到现在我不知道该怎么办了。已经没有当初学习的心劲了,好累呀,但是又不知道该干什么去。在家就是打游戏,boss简历投一投。每天日重一次。26秋招都说是针对26届的人,25怎么办。我好绝望。要不要参加考公、考研、央国企这些的。有没有大佬可以帮帮我。为什么感觉别人找工作都是顺其自然的事情,我感觉自己每一步都在艰难追赶。八股文背了又忘背了又忘,我每次都花很长时间去理解他,可是现在感觉八股、项目都忘完了。真的已经没有力气再去学习了。图片是我的简历,有没有大哥可以指正一下,或者说我应该走哪条路,有点不想在找工作了。
码客明:太累了就休息一下兄弟,人生不会完蛋的
如果实习可以转正,你会不...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务