华为OD机试真题【模拟商场优惠打折】

文章讲述了如何在模拟商场中,利用满减券、打折券和无门槛券的组合策略,为每个购物者找到使用优惠券后获得最低价格的方法,考虑了优惠券的数量限制和使用顺序对最终价格的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、题目描述

【模拟商场优惠打折】

模拟商场优惠打折,有三种优惠券可以用,满减券、打折券和无门槛券。
满减券:满100减10,满200减20,满300减30,满400减40,以此类推不限制使用;
打折券:固定折扣92折,且打折之后向下取整,每次购物只能用1次;
无门槛券:一张券减5元,没有使用限制。
每个人结账使用优惠券时有以下限制:
每人每次只能用两种优惠券,并且同一种优惠券必须一次用完,不能跟别的穿插使用(比如用一张满减,再用一张打折,再用一张满减,这种顺序不行)。
求不同使用顺序下每个人用完券之后得到的最低价格和对应使用优惠券的总数;如果两种顺序得到的价格一样低,就取使用优惠券数量较少的那个。

【输入描述】
第一行三个数字m,n,k,分别表示每个人可以使用的满减券、打折券和无门槛券的数量;
第二行一个数字x, 表示有几个人购物;
后面x行数字,依次表示是这几个人打折之前的商品总价。

【输出描述】
输出每个人使用券之后的最低价格和对应使用优惠券的数量

【示例1 】
输入
第一行三个数字m,n,k,分别表示每个人可以使用的满减券、打折券和无门槛券的数量。

3 2 5
3
100
200
400

输出:
65 6
135 8
275 8

说明
第一个人使用 1 张满减券和5张无门槛券价格最低。(100-10=90, 90-55=65)
第二个人使用 3 张满减券和5张无门槛券价格最低。(200-20-10-10=160, 160 – 5
5 = 135)
第二个人使用 3 张满减券和5张无门槛券价格最低。(400-40-30-30=300, 300 – 5*5=275)

2、解题思路

对每个购物者,计算使用四种优惠券组合的最终价格和使用优惠券的数量:
1.先使用满减券,再使用打折券。
2.先使用打折券,再使用满减券。
3.先使用满减券,再使用无i门槛券。
4.先使用打折券,再使用无门]槛券。

对计算出的结果按最终价格升序排序,价格相同时按使用优惠券数研序排序。输出排后的第一个结果, 即最低价格及对应使用优惠券的数量。

3、参考代码

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;


public class 模拟商场优惠打折 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            // 数字m,n,k,分别表示每个人可以使用的满减券、打折券和无门槛券的数量;
            int m = in.nextInt();
            int n = in.nextInt();  // 每次购物只能用1次
            int k = in.nextInt();  // 因无门槛,即留在最后使用

            int x = in.nextInt();

            int[] prices = new int[x];
            for (int i = 0; i < x; i++) {
                prices[i] = in.nextInt();
            }

            for (int price : prices) {
                List<int[]> modes = new ArrayList<>();
                modes.add(getModeA(price, m, n));
                modes.add(getModeB(price, m, n));
                modes.add(getModeC(price, m, k));
                modes.add(getModeD(price, n, k));

                modes.sort(((o1, o2) -> {
                    if (o1[0] == o2[0]) {
                        return o1[1] - o2[1];
                    }
                    return o1[0] - o2[0];
                }));

                System.out.println(modes.get(0)[0] + " " + modes.get(0)[1]);
            }
        }
    }

    // 先满减后打折
    public static int[] getModeA(int price, int m, int n) {
        int count = 0;
        for (int i = 0; i < m; i++) {
            price -= (price / 100) * 10;
            count++;
            if (price < 100) {
                break;
            }
        }
        price *= 0.92;
        count++;
        return new int[]{price, count};
    }

    // 先打折后满减
    public static int[] getModeB(int price, int m, int n) {
        int count = 0;
        price *= 0.92;
        count++;
        for (int i = 0; i < m; i++) {
            price -= (price / 100) * 10;
            count++;
            if (price < 100) {
                break;
            }
        }
        return new int[]{price, count};
    }

    // 先满减后无门槛
    public static int[] getModeC(int price, int m, int k) {
        int count = 0;
        for (int i = 0; i < m; i++) {
            price -= (price / 100) * 10;
            count++;
            if (price < 100) {
                break;
            }
        }

        for (int i = 0; i < k; i++) {
            price -= 5;
            count++;
            if (price <= 0) {
                break;
            }
        }
        return new int[]{price, count};
    }

    // 先打折后无门槛
    public static int[] getModeD(int price, int n, int k) {
        int count = 0;
        price *= 0.92;
        count++;
        for (int i = 0; i < k; i++) {
            price -= 5;
            count++;
            if (price <= 0) {
                break;
            }
        }
        return new int[]{price, count};
    }


}

4、相似题目

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值