Skip to content
On this page

bytedance-006.夏季特惠

image

格式:

输入:

  • 第一行包含两个数 n 和 X 。
  • 接下来 n 行包含每个游戏的信息,原价 ai,现价 bi,能获得的快乐值为 wi 。 输出:
  • 输出一个数字,表示你能获得的最大快乐值。 示例 1:

输入: 4 100 100 73 60 100 89 35 30 21 30 10 8 10 输出:100 解释:买 1、3、4 三款游戏,获得总优惠 38 元,总金额 102 元超预算 2 元,满足条件,获得 100 快乐值。 示例 2:

输入: 3 100 100 100 60 80 80 35 21 21 30 输出:60 解释:只能买下第一个游戏,获得 60 的快乐值。 示例 3:

输入: 2 100 100 30 35 140 140 100 输出:135 解释:两款游戏都买,第一款游戏获得优惠 70 元,总开销 170 元,超过预算 70 元,超出预算金额不大于获得优惠金额满足条件,因此可以获得最大快乐值为 135。 提示:

所有输入均为整型数

  • 1 <= n <= 500
  • 0 <= x <= 10,000
  • 0 <= b_i <= a_i <= 500
  • 1 <= w_i <= 1,000,000,000 关于数据集:
  • 前 30% 的数据, 小数据集 (n<=15)
  • 中间 30% 的数据,中等数据集 (n<=100)
  • 后 40% 的数据,大数据集 (n<=500)

AC

总优惠金额不低于超过预算的总金额

==> 总优惠金额 >= 总金额 - 总预算
==> 总金额-总优惠金额 <= 总预算
==> sum(产品现价 - 产品的优惠价格) <= 总预算
==> sum(产品现价 - (产品原价 - 产品现价)) <= 总预算
于是就转化为01背包问题。重量为(产品现价 - (产品原价 - 产品现价)),价值为快乐值
import java.util.Scanner;

class Solution {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int gameCount = scanner.nextInt();
        int money = scanner.nextInt();
        int[] previousValue = new int[gameCount];
        int[] nowValue = new int[gameCount];
        int[] happiness = new int[gameCount];
        for (int i = 0; i < gameCount; i++) {
            previousValue[i] = scanner.nextInt();
            nowValue[i] = scanner.nextInt();
            happiness[i] = scanner.nextInt();
        }
        // 获取现价-优惠金额的一个数组
        int[] values = new int[gameCount];
        for (int i = 0; i < values.length; i++) {
            values[i] = nowValue[i] - (previousValue[i] - nowValue[i]);
        }
        // 这里values的范围是[-500, 500],我们首先取所有<0的数
        int otherMoney = 0;
        long otherHappiness = 0;
        for (int i = 0; i < values.length; i++) {
            if (values[i] <= 0) {
                otherMoney += -values[i];
                otherHappiness += happiness[i];
            }
        }

        long res = otherHappiness + fun(values, money + otherMoney, happiness);
        System.out.println(res);
    }

    /**
     * volumes、values为每个物品的体积、价值,背包容量为capacity,求背包可以装的物品的最大价值
     */
    private static long fun(int[] volumes, int capacity, int[] values) {
        int count = volumes.length;
        // memo[i][j] 前i个物品,装在体积为j的背包中,可以得到的最大价值
        long[][] memo = new long[count + 1][capacity + 1];
        for (int i = 1; i < count + 1; i++) {
            for (int j = 1; j < capacity + 1; j++) {
                // 不选第i - 1个物品
                long num = memo[i - 1][j];
                if (volumes[i - 1] > 0 && j >= volumes[i - 1]) {
                    // 选择第i - 1个物品
                    num = Math.max(num, memo[i - 1][j - volumes[i - 1]] + values[i - 1]);
                }
                memo[i][j] = num;
            }
        }
        return memo[count][capacity];
    }
}