lotus

贵有恒何必三更眠五更起 最无益只怕一日曝十日寒

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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. 总结

posted on 2023-07-12 21:00  白露~  阅读(26)  评论(0编辑  收藏  举报