题解 | #购物单#

购物单

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

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int m = sc.nextInt();
        //1.接收数据,创建m商品;
        Goods[] goods = new Goods[m + 1];
        goods[0] = new Goods(0, 0, 0);
        //因为题目的flag,商品编号从1开始,故goods下标也从1开始,故要加1.
        int i = 1;
    while (sc.hasNext()) {
           goods[i++] = new Goods(sc.nextInt(), sc.nextInt(), sc.nextInt());
        }

        //2.根据flag标号,将附件依附在主件上;
        for (int j = 1; j < m + 1; j++) {
            if (goods[j].flag>0){
                if (goods[goods[j].flag].a1 == 0) //若当前主件仍未分配附件则添加该附件为附件1
                    goods[goods[j].flag].setA1(j);
                else if (goods[goods[j].flag].a2 == 0) //每个附件只能被加一次,一个主件最多可添加两个附件
                    goods[goods[j].flag].setA2(j);
            }
        }
     /*   for (Goods good : goods) {
            if(good.flag==0)
            System.out.println(good);
        }*/

        //对dp数组初始化 :dp[k][j]定义:手中有j元时,任买前0-i中的几件物品达到的最大满意度
        int[][] dp = new int[m + 1][N + 1]; //因为商品价格都是10的倍数,所以这里总钱数也可考虑成10的倍数.3600/10=360,0-359;故加1
        //不用考虑个位数非0,多出的个位数啥也买不起.对是否买得起不影响
        //当有0元时,啥也买不到,故所有j=0时dp为0;
        //对于k=0时0号商品价格和重要度都为0,默认0号为主件,故dp也为0;

        for (int k = 1; k < m + 1; k++) { //其实只用算购买主件的几种情况,附件和主件依附着卖.
            int price  = 0, price1  = 0, price2  = 0, price3  = 0;
            int weight = 0, weight1 = 0, weight2 = 0, weight3 = 0;
            //只买主件
            price = goods[k].price;
            weight = goods[k].weight * price;
            //主件+附件1
            if (goods[k].a1 > 0) {
                price1 = goods[goods[k].a1].price + price;
                weight1 = goods[goods[k].a1].weight * goods[goods[k].a1].price + weight;
            }
            //主件+附件2
            if (goods[k].a2 > 0) {
                price2 = goods[goods[k].a2].price + price;
                weight2 = goods[goods[k].a2].weight * goods[goods[k].a2].price + weight;
            }
            //主件+附件1,2
            if (goods[k].a1 > 0 && goods[k].a2 > 0) {
                price3 = goods[goods[k].a1].price + goods[goods[k].a2].price + price;
                weight3 = goods[goods[k].a1].weight * goods[goods[k].a1].price + goods[goods[k].a2].weight * goods[goods[k].a2].price + weight;
            }

            for (int j = 1; j <= N ; j++) {
                if (goods[k].flag > 0) dp[k][j] = dp[k - 1][j]; //当该物品为附件时不买,
                else {
                    dp[k][j] = dp[k - 1][j]; //问题出现在这儿,如果不直接赋给dp[k][j],而是在4个if里用dp[k-1][j]判断会出现有一个用例出错
                    //这样可以直接在5种情况中选出最大的;
                    if (j  >= price &&price  != 0) //price初始化时为0,肯定j>=price
                        dp[k][j] = Math.max(dp[k][j], dp[k - 1][j-price ] + weight );
                    if (j  >= price1&&price1 != 0)
                        dp[k][j] = Math.max(dp[k][j], dp[k - 1][j-price1] + weight1);
                    if (j  >= price2&&price2 != 0)
                        dp[k][j] = Math.max(dp[k][j], dp[k - 1][j-price2] + weight2);
                    if (j  >= price3&&price3 != 0)
                        dp[k][j] = Math.max(dp[k][j], dp[k - 1][j-price3] + weight3);
                    /*
                    *   错误代码,这里4个if之间没有进行比较,并且缺少和不买i时的比较,
                    *  因为就算主件有附件,也可以连主件都不买
                    * 故在该物品为主件时应当有5种情况:
                    * 1、不买;2、只买主件;3、买主件加附件1;4、买主件加附件2;5、买主件加附件1和附件2
                    * 在以上几种情况中选择最大的。
                    * eg:当买主件加附件1时,用dp[k-1][j-price1],j-price1是指当钱减去主件和附件1时的总钱数
                    * 这时如果买,则刚好够买。
                    *  if (j  >= price &&price  != 0) //price初始化时为0,肯定j>=price
                        dp[k][j] = Math.max(dp[k-1][j], dp[k - 1][j-price ] + weight );
                    if (j  >= price1&&price1 != 0)
                        dp[k][j] = Math.max(dp[k-1][j], dp[k - 1][j-price1] + weight1);
                    if (j  >= price2&&price2 != 0)
                        dp[k][j] = Math.max(dp[k-1][j], dp[k - 1][j-price2] + weight2);
                    if (j  >= price3&&price3 != 0)
                        dp[k][j] = Math.max(dp[k-1][j], dp[k - 1][j-price3] + weight3);
                    * */
                }
            }
        }
        System.out.println(dp[m][N]);
    }
}

class Goods {
    int price;//价格
    int weight;//重要度
    int flag;//是否为附件
    int a1 = 0, a2 = 0; //附件编号,为0说明没有附件

    public Goods(int price, int weight, int flag) {
        this.price = price;
        this.weight = weight;
        this.flag = flag;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "price=" + price +
                ", weight=" + weight +
                ", flag=" + flag +
                ", a1=" + a1 +
                ", a2=" + a2 +
                '}';
    }

    public void setA1(int a1) {
        this.a1 = a1;
    }

    public void setA2(int a2) {
        this.a2 = a2;
    }
}

全部评论

相关推荐

从小父母离异家里没人管,靠着心里的不安和学校的环境也算是坚持到了学有所成的地步。到了大学环境开始松散不知道该做什么,只觉得在不挂科的基础上能往上考多少就考多少,等到秋招来临才发现自己有多么幼稚无能,今年九月份初才发现自己原来连一个求职的方向都没有。因为之前做过前后端一体的课设,算是有过了解,而对于其他岗位连做什么都不知道,因此这一个半个月在越来越焦虑的同时埋头苦学,事到如今想要活下去我似乎只能走前端这条路了,9月初先是靠着虚假夸大能力的简历得到一些笔试来确定了考察的方向,有一个大厂的无笔试面试最终是拒绝了没有勇气去面对。然后在这个基础上埋头苦学,如今也算是搭好了自己前端学习的框架和思考的瞄,可以逐渐给自己扩展新的知识和能力了,但这并不是一件多好的事儿,因为我发现学的越多越焦虑,学的越多便越无力。因为我感觉我如今努力学习的知识都是竞争对手们早就掌握了的东西,我如今困惑追求答案的难题早就被别人解决。别人早就能得心应手地做出项目而我连思考都会卡壳,看着别人的笔试和面经上那些闻所未闻的题目,我才知道别人到底有多强而我有多幼稚,我什么时候才能达到别人那种堪称熟练的能力呢?而且网上的焦虑越多越多,即便是真有这么高的能力最后也大概落得一个低薪打工人的下场,我真的感到迷茫。秋招都快结束了,而我还在继续痛苦的学习之旅,这些天找前端面试发现似乎问的有些简单跟网上搜到的内容不符(可能因为并不是大厂),我是不是本来就没打算被招所以别人懒得细问呢?我不知道,我只能继续总结下去学习下去,不管如何我都要活下去,如果我能早一些准备就好了,如果暑假能意识到现在这个情况就好了,可惜没有如果。种下一棵树的最好时间是十年前,其次是现在,虽然我相信自己的学习能力,但已经错过了最好的时机,只能在焦虑与痛苦中每天坚持学下去。目前的路还有很长很长,先去把typescript看了,再去巩固vue3的基础,再去练习elementui的使用,如果这能找到实习的话就好了。接下来呢?去学uniapp和小程序,不管如何我都要对得起曾经努力的自己。即便我们都感到痛苦,但我心中还是希望我们都能靠自己的努力来获取自己想要的幸福。
紧张的牛牛等一个of...:在担心什么呢,有一手985的学历在,就算是小厂别人都会要的,咱们双非的人更多,多少还在沉沦的,怕什么了
一句话证明你在找工作
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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