题解 | #购物单#01背包问题 + 附件条件

购物单

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

1、如果只包含主件,则是经典的01背包问题
2、现在加了附件,则最大值有四种情况:主件、主件+附件1、主件+附件2、主件+附件1+附件2
第一步:记录原始数据
记录每个主件以及其附件的关系,并记录其 价格 * 重要度
第二步:遍历主件
记录主件在四种情况下的最大值
import java.util.Scanner;
public class Main {     public static void main(String[] args) {         Scanner in = new Scanner(System.in);         while (in.hasNextInt()) { // 注意 while 处理多个 case             int money = in.nextInt()/10;//钱数是10的倍数,除以10,降低时间和空间复杂度             int num = in.nextInt();             //读取输入,区分主件,附件             int[][] price = new int[num + 1][3];//记录主件和附件的价格             int[][] pPlusImportant = new int[num + 1][3];//记录主件和附件的价格 * 重要度             for(int i=1;i<=num;i++){                 int v = in.nextInt()/10;                 int p = in.nextInt();                 int q = in.nextInt();                 int im = v * p;                 if(q==0){                     price[i][0] = v;//第一列是主件价格,第二列是附件1的价格,第三列附件2的价格                     pPlusImportant[i][0] = im;                 }else{                     if(price[q][1]==0){                         price[q][1] = v;//主件q的附件1的价格                         pPlusImportant[q][1] = im;                     }else{                         price[q][2] = v;//主件q的附件2的价格                         pPlusImportant[q][2] = im;                     }                 }             }             int[] dp = new int[money + 1];//背包问题,带附加条件             for(int i=1;i<=num;i++){                 if(price[i][0] == 0){                     continue;//主件为空,则跳过                 }                 for(int j=money;j>=price[i][0];j--){                     int a = price[i][0];//主件                     int a1 = pPlusImportant[i][0];                     int b = price[i][1];//附件1                     int b1 = pPlusImportant[i][1];                     int c = price[i][2];//附件2                     int c1 = pPlusImportant[i][2];                     if(j>=a){                         dp[j] = Math.max(dp[j],dp[j-a] + a1);                     }                     if(j>=a+b){                         dp[j] = Math.max(dp[j],dp[j-a-b] + a1 + b1);                     }                     if(j>=a+c){                         dp[j] = Math.max(dp[j],dp[j-a-c] + a1 + c1);                     }                     if(j>=a+b+c){                         dp[j] = Math.max(dp[j],dp[j-a-b-c] + a1 + b1 + c1);                     }                 }             }             System.out.println(dp[money] * 10);//开始的时候总钱数除10,输出的时候*10         }     } }
全部评论
好好好
点赞 回复 分享
发布于 2023-09-29 22:59 北京
dp[j-a] 是什么意思,没懂
点赞 回复 分享
发布于 2022-12-15 16:04 江苏
就喜欢这种行行加注释的!对小白特别友好!谢谢大佬!
点赞 回复 分享
发布于 2022-09-02 17:04 广东
我是小白,请问48~50行,price[i][0] == 0为啥要跳过呀?跳过的话price[i][0] == 0对应附件的值不是赋不到b和c上面去了么。。。 示例2:输入 50 5,20 3 5,20 3 5,10 3 0,10 2 0,10 1 0 price[5][0] = 0 price[5][1] = 20 price[5][2] = 20 如果price[5][0] == 0跳过循环,那price[5][1]和price[5][2]的值就不能通过下面那个循环赋值给b和c了吧?
点赞 回复 分享
发布于 2022-06-15 22:47
评论区终于有一个对了的,怎么没有评论
点赞 回复 分享
发布于 2022-05-03 16:25

相关推荐

关于我大学本科四年,想了很多,但还是不知道该怎么动笔&nbsp;“大学四年,是我从懵懂少年走向职场青年的转折期。这一路跌跌撞撞,有迷茫,有遗憾,也有成长和决心。”&nbsp;大一刚进来时仍然有高中那股学习劲,经常一个人去图书馆学高等数学,但后面劲头一过便开始在宿舍开启躺平生活(现在想想那段时间真的很爽,无忧无虑)。由于大一担任班干部,所以经常要跟其他班的班干部交流,在此期间认识了隔壁班的一位女生,短发而很可爱,因为很多团建还有比赛都是我们两班一起参加的,而且我和她都是负责人,所以交集很多,后面慢慢地彼此对产生了好感,所以在大一刚开学的2个月后,我们在一起了,彼此之前都是初恋。但当时我真的是太太太直男了,对感情的想...
真烦好烦真烦:骗哥们可以,别把你自己也骗到了就行。哥们被你骗了真无所谓的,打个哈哈就过了。但希望你打完这段话后擦一下眼角,别让眼泪掉在手机屏幕上了就行。你说的这些话,哥们信一下也是没什么的。还能让你有个心里安慰,但这种话说出来骗骗兄弟就差不多得了,哥们信你一下也不会少块肉,但是你别搞得自己也当真了就行。哥们被你骗一下是真无所谓的,兄弟笑笑也就过去了。真不是哥们想要破你防,你擦擦眼泪好好想想,除了兄弟谁还会信你这些话?
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
48
16
分享

创作者周榜

更多
牛客网
牛客企业服务