首页 > 其他分享 >HJ16 购物单

HJ16 购物单

时间:2023-07-12 21:12:16浏览次数:40  
标签:goods HJ16 int 买主 a1 附件 购物单 dp

1. 题目

读题

HJ16 购物单

 

 

考查点

01背包 变种 

2. 解法

思路

 

代码逻辑

 

具体实现

 

import java.util.Scanner;

//定义一个物品类,用来存储每个物品的信息
class Good {
    int v; //物品价格
    int vp; //物品重要度乘价格
    int q; //物品是否为主件
    int a1; //附件1的编号
    int a2; //附件2的编号

    public Good(int v, int p, int q) {
        this.v = v;
        this.vp = v * p;
        this.q = q;
        this.a1 = 0;
        this.a2 = 0;
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt(); //总钱数
        int m = sc.nextInt(); //物品个数
        Good[] goods = new Good[m + 1]; //创建一个物品数组,下标从1开始
        for (int i = 1; i <= m; i++) {
            int v = sc.nextInt(); //物品价格
            int p = sc.nextInt(); //物品重要度
            int q = sc.nextInt(); //物品是否为主件
            goods[i] = new Good(v, p, q); //创建一个物品对象,存入数组中
            if (q > 0) { //如果是附件,就将其编号存入对应主件的属性中
                if (goods[q].a1 == 0) {
                    goods[q].a1 = i;
                } else {
                    goods[q].a2 = i;
                }
            }
        }
        int[][] dp = new int[m + 1][N + 1]; //创建一个二维数组,用来表示动态规划的状态
        for (int i = 1; i <= m; i++) { //遍历每个物品
            int v0, v1, v2, v3; //分别表示只买主件、买主件和附件1、买主件和附件2、买主件和附件1和附件2的总价格
            int vp0, vp1, vp2, vp3; //分别表示只买主件、买主件和附件1、买主件和附件2、买主件和附件1和附件2的总满意度
            v0 = goods[i].v; //只买主件的总价格就是主件价格
            vp0 = goods[i].vp; //只买主件的总满意度就是主件重要度乘价格
            v1 = v0 + goods[goods[i].a1].v; //买主件和附件1的总价格就是主件价格加附件1价格
            vp1 = vp0 + goods[goods[i].a1].vp; //买主件和附件1的总满意度就是主件重要度乘价格加附件1重要度乘价格
            v2 = v0 + goods[goods[i].a2].v; //买主件和附件2的总价格就是主件价格加附件2价格
            vp2 = vp0 + goods[goods[i].a2].vp; //买主件和附件2的总满意度就是主件重要度乘价格加附件2重要度乘价格
            v3 = v0 + goods[goods[i].a1].v + goods[goods[i].a2].v; //买主件和附件1和附件2的总价格就是主件价格加附件1价格加附件2价格
            vp3 = vp0 + goods[goods[i].a1].vp + goods[goods[i].a2].vp; //买主件和附件1和附件2的总满意度就是主件重要度乘价格加附件1重要度乘价格加附件2重要度乘价格

            for (int j = 1; j <= N; j++) { //遍历每个钱数
                if (goods[i].q > 0) { //如果是附件,就不买,继承上一个物品的状态
                    dp[i][j] = dp[i - 1][j];
                } else { //如果是主件,就比较四种方案中的最大满意度
                    dp[i][j] = dp[i - 1][j]; //默认不买当前物品
                    if (j >= v0) { //如果钱数大于等于只买主件的总价格,就比较不买和只买主件的满意度
                        dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - v0] + vp0);
                    }
                    if (j >= v1 && goods[i].a1 > 0) { //如果钱数大于等于买主件和附件1的总价格,且附件1存在,就比较不买、只买主件和买主件和附件1的满意度
                        dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - v1] + vp1);
                    }
                    if (j >= v2 && goods[i].a2 > 0) { //如果钱数大于等于买主件和附件2的总价格,且附件2存在,就比较不买、只买主件、买主件和附件1和买主件和附件2的满意度
                        dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - v2] + vp2);
                    }
                    if (j >= v3 && goods[i].a1 > 0 && goods[i].a2 > 0) { //如果钱数大于等于买主件和附件1和附件2的总价格,且附件1和附件2都存在,就比较不买、只买主件、买主件和附件1、买主件和附件2和买主件和附件1和附件2的满意度
                        dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - v3] + vp3);
                    }
                }
            }
        }
        System.out.println(dp[m][N]); //输出最大满意度
    }
}

3. 总结

标签:goods,HJ16,int,买主,a1,附件,购物单,dp
From: https://www.cnblogs.com/shoshana-kong/p/17548771.html

相关文章

  • 动态规划-HJ16 购物单
    描述王强决定把年终奖用于购物,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:主件附件电脑打印机,扫描仪书柜图书......
  • 华为面试题之购物单解答
    原题如下:题目描述王强今天很开心,公司发给N元的年终奖。王强决定把年终奖用于购物,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子: ......