200字
模拟商场优惠打折(Python)
2025-11-21
2025-11-22

题目描述

模拟商场优惠打折,有三种优惠券可以用,满减券、打折券和无门槛券。

满减券:满100减10,满200减20,满300减30,满400减40,以此类推不限制使用;

打折券:固定折扣92折,且打折之后向下取整,每次购物只能用1次;

无门槛券:一张券减5元,没有使用限制。

每个人结账使用优惠券时有以下限制:

每人每次只能用两种优惠券,并且同一种优惠券必须一次用完,不能跟别的穿插使用(比如用一张满减,再用一张打折,再用一张满减,这种顺序不行)。

求不同使用顺序下每个人用完券之后得到的最低价格和对应使用优惠券的总数;如果两种顺序得到的价格一样低,就取使用优惠券数量较少的那个。

用例

输入

3 2 5
3
100
200
400

输出

65 6
135 8
275 8

说明

输入:

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

输出:

第一个人使用 1 张满减券和5张无门槛券价格最低。(100-10=90, 90-5*5=65)

第二个人使用 3 张满减券和5张无门槛券价格最低。(200-20-10-10=160, 160 – 5*5 = 135)

第二个人使用 3 张满减券和5张无门槛券价格最低。(400-40-30-30=300, 300 – 5*5=275)

暴力枚举

  • 穷举所有合法组合:系统性地枚举所有可能的优惠券组合(3种组合 × 2种顺序)

  • 最优解选择:在所有合法方案中选择价格最低的,价格相同时选择用券最少的

算法实现

def fullSubtraction(price, max_t):
    """
    满减券:满100减10,满200减20,满300减30,满400减40,以此类推不限制使用;
    """
    current_price = price
    used_count = 0

    for _ in range(max_t):
        discount = (current_price // 100) * 10
        if discount == 0:  # 如果当前价格不满100,满减券无效
            break
        current_price -= discount
        used_count += 1

    return current_price, used_count


def discount(price):
    """
    使用1张打折券
    :param price: 原价
    :return: 使用后的价格
    """
    return int(price * 0.92)


def thresholdFree(price, k):
    """
    使用k张无门槛券
    :param price: 原价
    :param k: 使用的无门槛券数量
    :return: 使用后的价格
    """
    price -= 5 * k
    return max(price, 0)


def calculate_combo1(price, m, n):
    """组合1: 满减券 + 打折券"""
    results = []

    # 如果两种券都有,才考虑这个组合
    if m > 0 and n > 0:
        # 顺序A: 先满减后打折
        p1, used_m1 = fullSubtraction(price, m)  # 最多使用m张满减券
        p1 = discount(p1)
        count1 = used_m1 + 1
        results.append((p1, count1))

        # 顺序B: 先打折后满减
        p2 = discount(price)
        p2, used_m2 = fullSubtraction(p2, m)  # 最多使用m张满减券
        count2 = 1 + used_m2
        results.append((p2, count2))

    return results


def calculate_combo2(price, m, k):
    """组合2: 满减券 + 无门槛券"""
    results = []

    # 如果两种券都有,才考虑这个组合
    if m > 0 and k > 0:
        # 顺序A: 先满减后无门槛
        p1, used_m1 = fullSubtraction(price, m)  # 最多使用m张满减券
        p1 = thresholdFree(p1, k)
        count1 = used_m1 + k
        results.append((p1, count1))

        # 顺序B: 先无门槛后满减
        p2 = thresholdFree(price, k)
        p2, used_m2 = fullSubtraction(p2, m)  # 最多使用m张满减券
        count2 = k + used_m2
        results.append((p2, count2))

    return results


def calculate_combo3(price, n, k):
    """组合3: 打折券 + 无门槛券"""
    results = []

    # 如果两种券都有,才考虑这个组合
    if n > 0 and k > 0:
        # 顺序A: 先打折后无门槛
        p1 = discount(price)
        p1 = thresholdFree(p1, k)
        count1 = 1 + k
        results.append((p1, count1))

        # 顺序B: 先无门槛后打折
        p2 = thresholdFree(price, k)
        p2 = discount(p2)
        count2 = k + 1
        results.append((p2, count2))

    return results


def find_best_solution(price, m, n, k):
    """为单个顾客找到最优解决方案"""
    best_price = price
    best_count = 0

    # 计算所有可能的组合
    all_results = []
    all_results.extend(calculate_combo1(price, m, n))
    all_results.extend(calculate_combo2(price, m, k))
    all_results.extend(calculate_combo3(price, n, k))

    # 如果没有任何组合(比如券都用完了),返回原价
    if not all_results:
        return price, 0

    # 找到最优解
    for result_price, result_count in all_results:
        if result_price < best_price or (result_price == best_price and result_count < best_count) or best_count == 0:
            best_price = result_price
            best_count = result_count

    return best_price, best_count


def main():
    """主函数:处理输入和输出"""
    # 读取输入
    m, n, k = map(int, input().split())
    x = int(input())
    prices = [int(input()) for _ in range(x)]

    # 为每个顾客计算最优方案
    for price in prices:
        best_price, best_count = find_best_solution(price, m, n, k)
        print(best_price, best_count)


if __name__ == "__main__":
    main()

注意网上还有一道类似的题:

题目描述

某网上商场举办优惠活动,发布了满减、打折、无门槛3种优惠券,分别为:

  • 每满100元优惠10元,无使用数限制,如100~199元可以使用1张减10元,200~299可使用2张减20元,以此类推;

  • 92折券,1次限使用1张,如100元,则优惠后为92元;

  • 无门槛5元优惠券,无使用数限制,直接减5元。

优惠券使用限制

  • 每次最多使用2种优惠券,2种优惠可以叠加(优惠叠加时以优惠后的价格计算),以购物200元为例,可以先用92折券优惠到184元,再用1张满减券优惠10元,最终价格是174元,也可以用满减券2张优惠20元为180元,再使用92折券优惠到165(165.6向下取整),不同使用顺序的优惠价格不同,以最优惠价格为准。在一次购物种,同一类型优惠券使用多张时必须一次性使用,不能分多次拆开使用(不允许先使用1张满减券,再用打折券,再使用一张满减券)。

问题

  • 请设计实现一种解决方法,帮助购物者以最少的优惠券获得最优的优惠价格。优惠后价格越低越好,同等优惠价格,使用的优惠券越少越好,可以允许某次购物不使用优惠券。

约定

  • 优惠活动每人只能参加一次,每个人的优惠券种类和数量是一样的。

用例

输入

3 2 5
3
100
200
400

输出

65 6
155 7
338 4

说明

输入:

  • 第一行:3种优惠券数量分别为:满减券3张,打折券2张,无门槛5张

  • 第二行:总共3个人购物

  • 第三行:第一个人购物优惠前价格为100元

  • 第四行:第二个人购物优惠前价格为200元

  • 第五行:第三个人购物优惠前价格为400元

输入3个人,输出3行结果,同输入的顺序,对应每个人的优惠结果,如下:

  • 第一行输出:先使用1张满减券优惠到90元,再使用5张无门槛券优惠到25元,最终价格是65元,总共使用6张优惠券。

  • 第二行输出:先使用2张满减券优惠到180元,再使用5张无门槛券优惠到25元,最终价格是155元,总共使用7张优惠券。

  • 第三行输出:先使用1张92折券优惠到368元,再使用3张满减券优惠到30元,最终价格是338元,总共使用4张优惠券。


其中关于满减券的使用逻辑不同,导致最终实现也不同。本题和上面链接题目应该属于AB卷题目,防止作弊的。

模拟商场优惠打折,这题关于满减券的使用逻辑:

def fullSubtraction(price, max_t):
    """
    每满100元优惠10元,无使用数限制,如100~199元可以使用1张减10元,200~299可使用2张减20元,以此类推;
    :param price: 原价
    :param max_t: 最多可使用的满减券数量
    :return: (使用后的价格, 实际使用的券数)
    """
    count = min((price // 100), max_t)
    price -= count * 10
    return price, count

模拟商场优惠打折(Python)
作者
Shisuiyi
发表于
2025-11-21
License
CC BY-NC-SA 4.0

评论