基于商品数量折扣的家电采购策略优化及代码改进问询
家电采购折扣优化问题
折扣规则
商店按单次购买的商品数量提供如下阶梯折扣:
- 购买2件:该组内最低价商品享25%折扣
- 购买3件:该组内最低价商品享55%折扣
- 购买4件:该组内最低价商品享80%折扣
- 购买5件:该组内最低价商品享99%折扣
需求目标
确定最优采购分组策略,最大化总折扣节省(即最小化采购总成本)。例如:
- 采购5件时,对比「一次性买5件」和「分2件+3件两次购买」哪种更划算
- 采购多件商品(如A、B、C、D、E)时,需遍历所有可能的分组组合(如
[(A,B),(C,D,E)]、[(A,B),(C,D),E]等),筛选出总节省最高的方案
原代码实现
from itertools import combinations products = { 'fridge': 3009, 'washing_machine': 1449, 'stove': 2299.99, 'dish_washer': 1599, 'tv': 3999, 'oven': 1899 } def get_discount(n_products: int) -> float: discounts = { 1: 0., 2: .25, 3: .55, 4: .8, 5: .99 } return discounts[n_products] def get_prices(in_products: list) -> list: prices = [] for i in range(len(in_products)): prices.append(products[in_products[i]]) return sorted(prices,) def get_best_pair(products: dict, n_products: int) -> tuple: max_saved = -9999 best_pair = None best_discount = None for pair in combinations(products.keys(), n_products): prices = get_prices(pair) discount = get_discount(n_products) tot_price = sum(prices) prices[0] -= prices[0] * discount tot_discounted_price = sum(prices) saved = tot_price - tot_discounted_price if saved > max_saved: max_saved = saved best_pair = pair best_discount = tot_discounted_price print(pair, prices, tot_price, tot_discounted_price, saved, max_saved) return best_pair, max_saved, best_discount n_products = 5 results = {} for i in range(2, n_products + 1): to_buy = products.copy() buy_strategy = [] tot_saved = 0. tot_price = 0. print(f'{i}, to buy: {to_buy}, products: {products}') best_pair, saved, best_discount = get_best_pair(to_buy, i) buy_strategy.append(best_pair) tot_price += best_discount tot_saved += saved for product in best_pair: to_buy.pop(product) if len(to_buy) == 1: buy_strategy.append(*(to_buy.keys())) tot_price += [*to_buy.values()][0] print(f'Best combination for: {best_pair}, total discounted price: {tot_price}, tot saved: {saved}') left_to_buy = to_buy.copy() if len(left_to_buy) >= 2: for j in range(2, len(left_to_buy) + 1): left_to_buy = to_buy.copy() left_to_buy_strategy = buy_strategy.copy() left_to_buy_tot_price = tot_price left_to_buy_tot_saved = tot_saved print(f'{j}, to buy: {to_buy}, left to buy: {left_to_buy}') best_pair, saved, best_discount = get_best_pair(left_to_buy, j) left_to_buy_strategy.append(best_pair) left_to_buy_tot_price += best_discount left_to_buy_tot_saved += saved print(f'Best combination for: {best_pair}, total discounted price: {best_discount}, tot saved: {saved}') for product in best_pair: left_to_buy.pop(product) if len(left_to_buy) == 1: print(f'left to buy: {left_to_buy}, price: {[*left_to_buy.values()][0]}') left_to_buy_strategy.append([*left_to_buy.keys()][0]) left_to_buy_tot_price += [*left_to_buy.values()][0] strategy_key = 'buy_strategy' + str(i) + str(j) results[strategy_key] = buy_strategy sep = '-' * 15 + '\n' print(f'{sep}Buy strategy {left_to_buy_strategy}\nTot price: {left_to_buy_tot_price}\nTot saved: {left_to_buy_tot_saved}\n{sep}')
优化方案与代码实现
优化思路
- 简化核心计算:将「计算一组商品的折扣节省」封装为独立函数,避免重复逻辑
- 遍历所有分组可能:通过递归枚举所有合法的分组组合(如6件商品可分为5+1、4+2、3+3、2+2+2等),计算每种组合的总节省
- 全局最优筛选:对比所有分组方案的总节省,保留最大值对应的策略
- 可读性提升:使用清晰的变量名、函数注释,拆分复杂逻辑
优化后代码
from itertools import combinations from typing import List, Dict, Tuple # 折扣规则:键=购买数量,值=最低价商品的折扣率 DISCOUNT_RULES = { 1: 0.0, 2: 0.25, 3: 0.55, 4: 0.80, 5: 0.99 } def calculate_group_savings(prices: List[float], group_size: int) -> float: """计算一组商品的折扣节省金额""" sorted_prices = sorted(prices) discount = DISCOUNT_RULES[group_size] # 仅对组内最低价商品打折 return sorted_prices[0] * discount def get_all_possible_groups(products: Dict[str, float], min_size: int = 2) -> List[Tuple[Tuple[str, ...], Dict[str, float]]]: """生成所有可能的商品分组(从min_size到最大允许的5件),返回(分组, 剩余商品)的列表""" possible_groups = [] max_group_size = min(5, len(products)) for size in range(min_size, max_group_size + 1): # 生成所有该尺寸的商品组合 for group in combinations(products.keys(), size): # 计算剩余商品 remaining = {k: v for k, v in products.items() if k not in group} possible_groups.append((group, remaining)) return possible_groups def find_optimal_strategy(products: Dict[str, float]) -> Tuple[float, List[Tuple[str, ...]]]: """递归查找最优采购策略,返回(总节省金额, 分组策略)""" product_count = len(products) # 终止条件:无商品或只剩1件(无折扣) if product_count <= 1: return 0.0, [] max_total_savings = -1 best_strategy = [] # 遍历所有可能的初始分组 for group, remaining_products in get_all_possible_groups(products): # 计算当前分组的节省 group_prices = [products[item] for item in group] group_savings = calculate_group_savings(group_prices, len(group)) # 递归计算剩余商品的最优节省 remaining_savings, remaining_strategy = find_optimal_strategy(remaining_products) # 总节省 total_savings = group_savings + remaining_savings # 更新最优策略 if total_savings > max_total_savings: max_total_savings = total_savings best_strategy = [group] + remaining_strategy # 处理剩余1件的情况(直接加入策略,无折扣) if len(best_strategy) == 0 and product_count == 1: best_strategy = [(next(iter(products.keys())),)] return max_total_savings, best_strategy # 示例使用 if __name__ == "__main__": products = { 'fridge': 3009, 'washing_machine': 1449, 'stove': 2299.99, 'dish_washer': 1599, 'tv': 3999, 'oven': 1899 } total_savings, optimal_strategy = find_optimal_strategy(products) original_total = sum(products.values()) final_cost = original_total - total_savings print("=== 最优采购策略 ===") print(f"总原价: {original_total:.2f}") print(f"总节省: {total_savings:.2f}") print(f"最终成本: {final_cost:.2f}") print("分组方案:") for idx, group in enumerate(optimal_strategy, 1): group_prices = [products[item] for item in group] group_size = len(group) savings = calculate_group_savings(group_prices, group_size) print(f" 第{idx}组: {group} | 组内节省: {savings:.2f}")
内容的提问来源于stack exchange,提问作者drkg4b
相关产品推荐
相关产品推荐

