为什么优惠券叠加需要"算法"?
大促结算前,购物车里躺着 2100 元的商品,手里攒了 8 张券:有满减、有折扣、有红包,还有品类券。随手把能用的全勾上,付款页只减了一两百;而群里"别人"同样的购物车却省出三百多。差别在哪?在优惠券叠加的顺序与选择上。
优惠券叠加不是"能用就全用",而是一个有约束的优化问题:同层券互斥、跨层券按固定顺序计算、满减券的含金量还随订单金额变化。本文用贪心策略和最优解两套思路,把券组合算法拆开讲透,并给出 30 秒心算的交叉点公式,帮你每次下单都算出最大优惠。
第一步:先给券分类,弄清"谁和谁能叠加"
叠加的第一步不是算,而是分类。主流电商平台的优惠券大致分四个层级,层内互斥、跨层叠加:
| 层级 | 券种 | 典型规则 | 计算顺序 |
|---|---|---|---|
| 单品级 | 店铺折扣券、单品直降 | 作用在单件商品价格上 | 最优先 |
| 订单级 | 跨店满减、店铺满减 | 按订单金额满额减免 | 第二 |
| 品类级 | 品类券、类目券 | 限定品类订单金额 | 第三 |
| 支付级 | 红包、支付优惠、消费券 | 减在最终应付金额上 | 最后 |
层内互斥意味着:同为折扣券,你通常只能选一张;同为满减券,满300减50和满500减80也只能二选一。所以"叠加最大化"的真实问题有两个:选哪张、按什么顺序。关于同层券为什么互斥、哪些券不能一起用,可参考满减叠加限制全解。
核心算法一:满减 vs 折扣,交叉点公式
先解决最常见的二选一:一张"满减券"和一张"折扣券",只能用一个,怎么选?
关键洞察:满减券的等效折扣率 = 减免额 ÷ 门槛,它随订单金额增大而衰减;折扣券的省金额 = 订单金额 × 折扣率,随金额线性增长。两者必然相交,交点就是决策分界线:
# 满减券"满A减B",折扣券折扣率 d(如9折则 d=0.1)
# 折扣券省额 = P × d;满减券省额 = B(固定)
# 交叉点:P × d = B → P* = B / d
def choose_coupon(price, manjian_A, manjian_B, discount_rate):
if price < manjian_A:
return "折扣券" # 未满门槛,满减券不可用
crossover = manjian_B / discount_rate
return "折扣券" if price > crossover else "满减券"
# 例:满300减50 vs 9折券(d=0.1)
# crossover = 50 / 0.1 = 500 元
# 买400元:满减省50,折扣省40 → 用满减券
# 买600元:满减省50,折扣省60 → 用折扣券
验证一遍:买 400 元商品,满300减50 省 50 元;9 折券省 400×0.1=40 元,满减券赢。买 600 元,满减仍只省 50;折扣券省 60 元,反超。交叉点 500 元处两者持平。这个公式心算只要两步,是优惠券叠加里最实用的贪心判断。
注意一个陷阱:如果折扣券带"上限"(如最高减 40 元),它的省金额 = min(P×d, 上限),封顶后不再随金额增长,交叉点公式失效。此时上限÷折扣率 = 有效封顶金额,超过该金额后折扣券永远输给固定满减。下单前先看券面小字。
核心算法二:多券叠加与最优选择
当券可以跨层叠加时,总优惠 = 各层优惠之和,但顺序影响结果。以最常见的"折扣券 + 满减 + 红包"为例,先折扣后满减通常优于先满减后折扣,因为折扣比例作用在更大的基数上:
# 场景:标价 400 元,9 折券 + 满300减50 + 10 元红包
# 方案A(先折扣后满减):
# 400×0.9 = 360 → 360-50 = 310 → 310-10 = 300 元
# 方案B(先满减后折扣):
# 400-50 = 350 → 350×0.9 = 315 → 315-10 = 305 元
# 结论:方案A比方案B省 5 元
原因很直观:先打 9 折,折扣基数按原价 400 算;先满减,基数被砍到 350,折扣额跟着缩水 5 元。虽然大多数平台的计算顺序是固定的,但理解这个原理能帮你在"同层券选择"时做出正确判断,也解释了为什么折扣率 vs 满减率在不同金额下结论不同。
若某一层内有多个候选(比如三张互斥折扣券),贪心做法是:预估每张券的省金额 = min(金额×折扣率, 上限),从大到小逐个试。更严谨的做法是动态规划——把"已用券集合"作为状态逐张枚举,思路与凑单最优解算法同构:
# 券分四层,每层最多取1张:dp[k] = 用前k层券后的最小实付
# 每层内部枚举候选券,取实付最小的那张
# 个人场景券数 ≤ 10,穷举 2^10=1024 种组合也完全可行
# 理解DP的意义:带门槛/上限时,"局部最省"未必是"全局最优"
实战推演:一次下单,四层券全叠加
以一次大促购物为例,规则按主流平台现行叠加顺序(单品级→订单级→品类级→支付级):
购物车:手机 1999 元 + 数据线 49 元 + 保护壳 52 元,合计 2100 元 手上有:店铺 9 折券(上限减 100)、跨店满 300 减 50、数码品类券满 200 减 20、平台红包 15 元
逐步计算:
- 单品级:9 折券作用在手机 1999 元上,理论省 199.9 元,但上限封顶,实省 100 元
- 订单级:跨店满 300 减 50,实省 50 元(优惠门槛按各平台规则计算,以页面展示为准)
- 品类级:数码品类券满 200 减 20,实省 20 元
- 支付级:红包 15 元,实省 15 元
总实付:2100 − 100 − 50 − 20 − 15 = 1915 元,四层合计省 185 元。
| 方案 | 计算链 | 实付 | 省金额 |
|---|---|---|---|
| 只用满减+红包 | 2100−50−15 | 2035 元 | 65 元 |
| 加9折券(漏品类券) | 2100−100−50−15 | 1935 元 | 165 元 |
| 四层全叠加(最优) | 2100−100−50−20−15 | 1915 元 | 185 元 |
对比很清楚:多叠一层品类券,省金额从 165 元跳到 185 元;而漏掉 9 折券更是直接损失 100 元。每层券都值得花 10 秒检查一遍,这就是优惠券叠加最大化的日常价值。多层优惠同时存在时怎么算总账,可进一步阅读三重叠加数学模型。
总结与建议
优惠券叠加的算法本质,是先分类、再比较、后组合。三个要点:
- 先分层:把券按单品级/订单级/品类级/支付级归类,层内互斥选最优,跨层尽量全叠
- 用交叉点公式:满减 vs 折扣,P* = B ÷ d,金额超过交叉点用折扣券,否则用满减券;折扣券带上限时另算封顶
- 顺序有讲究:折扣先于满减更优;多券组合时宁可枚举验证,也别只凭直觉
下次大促结算前,把购物车金额和券面规则列出来,按本文的流程走一遍,通常能比"随手勾选"多省 5%~10%。想快速算出最优组合,可以直接用凑单计算器验证,或回顾折扣率计算公式详解掌握基础算法。