案例 071 月卡 60 次够不够

案例 071 月卡 60 次够不够

摘要:月卡 199 元限 60 次,26 个工作日日均换 2.4 次,一个月要 62 次,多出来的 2 次按 2 元/次补。这笔账手算得出 203 元,但真正的问题在后面:超到什么程度该买第二张卡? 把「1 张卡 + 超次」「2 张卡」「全按次」写成一条分段成本曲线(式 5),答案被两个折点夹住:60 次和 120 次。本案 62 次的成本是 203 元,买两张卡是 398 元、多付 195 元,全按次 279 元、贵 76 元——第二张卡只有在超次单价高于 3.32 元/次时才可能翻盘,而在 2 元/次的价目下它永远买不划算。把这套账放到随机需求上:月需求服从泊松(均值 62.0 次),爆表概率 57%,期望超次 4.22 次、期望成本 207.4 元——月卡买的是「前 60 次 3.32 元/次的批发价」,风险全压在 60 次之后的那条尾巴上。

关键词:配额制定价;分段线性成本;整数规划;泊松需求;超次风险;灵敏度分析

1 问题提出

1.1 问题是什么

换电运营商卖月卡:199 元,一个月 60 次,超出部分 2 元一次。骑手 26 个工作日日均换电 2.4 次,一个月要 62 次,比配额多 2 次。于是最朴素的账是:\(199+2\times 2=203\) 元。

是不是该多买一张卡?第二张卡也是 199 元、也是 60 次。如果一个月要 100 次,两张卡 398 元,比「一张卡 + 40 次超次」的 279 元贵得多——直觉上第二张卡很贵,但贵到什么程度、在什么需求区间才值得,需要算清楚。

表 1 九个代表工作日的换电次数(全 26 天见 data_071.csv)

日期 星期 \(k_{t}\) /次 累计 /次 超次 /次 \(p_{t}\) /元
D01 周一 3 3 0 3.32
D05 周五 2 12 0 3.32
D10 周五 2 24 0 3.32
D11 周一 4 28 0 3.32
D15 周五 2 37 0 3.32
D20 周五 2 49 0 3.32
D24 周四 2 59 0 3.32
D25 周五 2 61 1 2.00
D26 周六 1 62 2 2.00

1.2 为什么不是「除以 2」

常见的错误算法是:第二张卡 199 元,超次 2 元一次,所以超次超过 \(199/2=99.5\) 次才该买第二张卡。这个算法漏了一件事:第二张卡自己也只带 60 次配额。月需求 \(D\) 落在 60 到 120 之间时,第二张卡能省下的超次最多 60 次,也就是最多 120 元,永远追不上 199 元的卡费;只有当超次单价涨到 \(199/60=3.32\) 元/次以上,第二张卡才开始有存在的意义(式 6)。

第二件事是按次付费的对照。不买卡按 4.5 元/次,60 次就是 270.0 元,比月卡贵 71 元;所以月卡在需求超过 44 次时就该买。44 次、60 次、120 次——三个折点把这件事切成四段,这就是本案的全部结构。第三件事是需求不是常数:日均 2.4 次是均值,某周爆单、某周下雨,月需求会上下摆,摆过 60 次的那几个月要额外掏钱,这部分是期望成本,不是账面成本。

1.3 Gurobi 如何求解

基模型只有 27 个变量:26 个每日换电次数 \(k_{t}\in\mathbb{Z}^{+}\) 加 1 个超次总数 \(s\),目标是 \(199+2s\),约束是 \(\sum_t k_t=D\) 与 \(s\ge\sum_t k_t-60\)。它是个几乎退化的整数规划——目标只依赖总次数,\(k_t\) 怎么摊都不影响最优值,这一点本身就是结论:日粒度在这道题里不提供任何自由度,真正有自由度的是「买几张卡」。

所以扩展版把购卡张数 \(y\in\{0,1,2\}\) 和购卡开关 \(z\) 抬成决策变量,模型自己会在「不买 / 一张 / 两张」之间选(式 1—式 4)。31 个变量、30 余条约束,每次求解不到 0.01 s;主方案加 7 点需求扫描、20 点热图、5 点卡费扫描、8 点前沿,合计 3 s 内跑完。

2 数学模型

2.1 符号说明

\(t=1,\dots,26\) 为工作日;\(k_{t}\) 为第 \(t\) 天的换电次数;\(D\) 为月度总需求(本案 62 次);\(s\) 为超次总数;\(u\) 为不买卡时按次计费的次数;\(y\) 为购卡张数(\(0\le y\le 2\));\(z\in\{0,1\}\) 表示是否买卡;\(c_{u}=4.5\) 元/次为按次单价;\(p=2\) 元/次为超次单价;月卡 199 元、配额 60 次/张。

2.2 目标函数

\[\min\ C=199\,y+2\,s+c_{u}\,u\tag{1} \]

三项分别对应卡费、超次费、按次费。\(u\) 是「没买卡的那条路」的计价通道:不买卡时全部次数走 \(u\),买卡时 \(u\) 被压到 0(式 4)。把三种付费方式写进同一个目标,模型才有资格告诉你「买几张」。

2.3 约束条件

\[\sum_{t=1}^{26}k_{t}=D,\qquad k_{t}\in\mathbb{Z}^{+},\quad t=1,\dots,26\tag{2} \]

26 天的次数加起来必须等于月需求。\(k_{t}\) 是整数,但目标只依赖它们的和,所以这条约束实际上把「日粒度」压成了一个标量——这是本案第一个教学点:变量维度不等于模型维度。

\[s\ \ge\ \sum_{t=1}^{26}k_{t}-60\,y,\qquad 0\le y\le 2,\qquad y\le 2z,\qquad z\le y\tag{3} \]

超次按「总次数减去 60 乘以卡张数」计。注意右边的 \(60y\) 是随卡张数线性增长的配额,这是双卡问题的关键:\(y=2\) 时配额 120 次,超次从第 121 次才开始算。

\[u\ \ge\ \sum_{t=1}^{26}k_{t}-M\,(1-z),\qquad u\ge 0,\qquad M=400\tag{4} \]

大 M 门控:\(z=0\) 时 \(u\ge D\),全部走按次;\(z=1\) 时 \(u\ge D-400<0\),被非负约束压到 0。\(y\le 2z\) 与 \(z\le y\) 一对把「买卡」和「买几张」绑死,避免出现「花了 0 张卡却享受了配额」的漏洞。

2.4 分段成本与临界点

\[C^{\mathrm{seg}}(D)=\min\Big\{c_{u}D,\ 199+2\,(D-60)^{+},\ 398+2\,(D-120)^{+}\Big\}\tag{5} \]

三个方案取最小就是真实成本函数,图 1 的三条线画的就是它。两个折点:\(D=60\) 处斜率从 3.32 元/次跳到 2 元/次;\(D=120\) 处斜率再跳回 2 元/次(第二张卡的配额用尽)。分段函数的斜率就是边际成本,这正是图 10 右轴那条阶梯线的含义。

\[p^{*}=\frac{199}{60}=3.32\ \text{元/次}\quad\Longleftrightarrow\quad \text{第二张卡才开始划算}\tag{6} \]

2.5 随机需求下的期望成本

\[\mathbb{E}[C]=199+2\,\mathbb{E}\big[(D-60)^{+}\big],\qquad D\sim \mathrm{Poisson}(26\mu)\tag{7} \]

日均 2.4 次乘以 26 天是 62.4 次(数据取整为 62 次、日均 2.38 次),若日需求独立同分布,月度总需求服从均值 62.0 的泊松分布。期望超次次数用 \((D-60)^{+}\) 的期望算——它不是 \(62.4-60=2.4\) 次,而是 4.22 次:需求低于 60 的月份超次为 0,但需求高于 60 的月份超得更多,这个不对称把期望抬高了将近一倍。

3 Gurobi 求解实现

3.1 建模要点

md.addConstr(gp.quicksum(k[t] for t in range(26)) == D)
md.addConstr(s >= gp.quicksum(k[t] for t in range(26)) - QUOTA * y - 400 * (1 - z))
md.addConstr(s <= 400 * z)                                            # 不买卡则超次为 0
md.addConstr(y <= NMAX * z); md.addConstr(z <= y)                     # 买卡与张数绑死
md.addConstr(u >= gp.quicksum(k[t] for t in range(26)) - 400 * z)     # z=0 时全走按次
md.setObjective(ccard * y + p * s + cuse * u, GRB.MINIMIZE)

两个坑。第一,配额项写成常数 60 而不是 \(60y\),模型会认为第二张卡白送配额,双卡方案在需求 100 次时算出 199 元——这是分段定价建模最常见的错。第二,\(z\) 与 \(y\) 之间只写 \(y\le 2z\) 不够:\(z=1,y=0\) 时卡费为 0、超次却按 \(\sum k\) 停在第 60 次之后,会出现「不花钱买卡却按 2 元超次」的虚假便宜解,必须补 \(z\le y\)。

3.2 求解结果

表 2 三方案月度口径对比($D=62$ 次/月,超次 2 元/次,按次 4.5 元/次)

方案 固定费 /元 配额 /次 超次 /次 超次费 /元 月成本 /元 单次成本 /元
1 张卡 + 超次 199 60 2 4 203 3.27
2 张卡 398 120 0 0 398 6.42
全按次 0 0 62 — 279 4.50

三行并排看:1 张卡 203 元、2 张卡 398 元、全按次 279 元。单次成本从 3.27 元到 4.50 元,差 1.23 元——月卡的本质是把单次成本从 4.5 元砍到 3.3 元,超次 2 元只是「买多了不亏」的兜底价。模型选 1 张卡、超次 2 次,与手算一致,说明这道题的难点不在求解,在把价格结构写对。

4 结果分析

图 1 月卡的成本结构:三段分段线性,60 次与 120 次是两个折点

4.1 成本结构 图 1 把三种付费方式画在同一张图上:按次是过原点的直线(4.5 元/次),1 张卡是 203 元起步、60 次后按 2 元/次爬升,2 张卡是 398 元起步、120 次后才爬升。本案 62 次落在 1 张卡那段 2 元斜线上。两卡曲线在 60—120 区间全程高于一卡曲线 195 元,这就是「第二张卡买不划算」的几何证明。

图 2 泊松抽样下月需求与总成本的散点,气泡为超次次数

4.2 需求—成本画像 图 2 是泊松抽样 4000 个月的(月需求,月成本)散点,气泡面积是超次数。点云在 60 次处竖直断开:左边全部压在 199 元的水平线上,右边沿 2 元斜率爬升。2302 个月爆表、占 58%,均值成本 207.6 元——账面 203 元是「计划值」,207.4 元才是「预算值」,两者差的是一个右尾。

图 3 三种付费方案的月成本对比,1 张卡最省

4.3 三方案对比 图 3:203 / 398 / 279 元。2 张卡多付 195 元,全按次贵 76 元。值得注意的是两卡方案的失败方式与按次不同:按次是「单价贵」,两卡是「配额用不完」——62 次的需求买 120 次配额,等于花 398 元买了 3.2 元/次的电,比月卡超次后的 2 元还贵。

图 4 26 天累计换电次数与 60 次配额线,第 25 天越线

4.4 26 天累计过程 图 4 是累计换电次数与 60 次配额线。第 25 天累计到 61 次,越线;第 26 天到 62 次,超 2 次。柱子高低不齐(最少 1 次、最多 4 次),但累计曲线几乎是一条直线——日需求的波动在月尺度上被平均掉了,这也解释了为什么 \(k_t\) 的自由度对最优值没有贡献。

图 5 日均需求对月成本与超次次数的影响(双轴)

4.5 日需求主灵敏度 图 5 左轴成本、右轴超次次数。日均从 2.0 提到 3.2 次,月成本从 199 元升到 245 元,超次从 0 次升到 23 次。曲线在 2.3 次处拐弯(对应 60 次配额):拐点之前成本是水平线 199 元、超次恒为 0;拐点之后日均每提高 0.2 次(月需求 +5 次)就多约 10 元/月,斜率恰好是 2 元/次乘以 5 次。整条扫描线上模型始终只买 1 张卡——在 2 元/次的价目下,双卡无论需求多高都追不平卡费(式 6),这就是「临界点在单价上、不在需求上」的直接证据。

图 6 日均需求 × 超次单价的成本热图,星标为本案参数

4.6 需求 × 超次单价 图 6 是 4×5 热图,行是日均需求、列是超次单价。同一行自左向右(日均 2.0):199 → 199 元,超次单价从 1 元涨到 4 元一分钱不花,因为需求没越线、超次为 0;同一列自上而下(单价 4 元):199 → 291 元,涨 92 元。单价只在越线之后才有杀伤力,需求才是主因。 本案参数(2.4 次、2 元)落在星标处,整个网格的取值范围是 199—291 元,极差 92 元。

图 7 月卡价格对最优成本与购卡张数的影响(第三维)

4.7 卡费(第三维) 图 7 横轴是月卡价格,从 159 元到 239 元,最优成本从 163 元升到 243 元,斜率接近 1——卡费涨 1 元,月成本就涨 1 元,一分都转嫁不掉。右轴显示整个过程都只买 1 张卡:卡费 239 元时月成本 243 元,仍低于全按次的 279 元,因为卡费要涨到 275 元才会被按次方案反超。

图 8 保障次数—最低成本前沿,灰区为保障不足的爆表风险区

4.8 保障前沿 图 8 横轴是要保障的换电次数、纵轴是最低成本。保障 40 次按次买只要 180.0 元,保障 50 次就跳到月卡 199 元,之后每多保障 15 次加 30 元(2 元/次的超次斜率),到 120 次累计 319 元。灰色区域是「保障不足」区:需求 P90=72 次、P95=75 次,本案只按 62 次做预算,意味着十个月里有两个月会不够——不是买错卡,而是预算做在均值上、风险留在尾部。

图 9 月度需求分布与累计概率,红色为超配额部分

4.9 月度需求分布 图 9 是泊松(均值 62.0 次)的概率柱与累计曲线,红色是超过 60 次的部分。爆表概率 57%、期望超次 4.22 次,也就是说六成的月份要额外掏 2—10 元。累计曲线在 60 次处只有 43%,在 80 次处到 99%——尾部不厚,但足够长,长到值得在预算里留一格。

图 10 不同日均需求下的成本构成与边际成本

4.10 成本构成与边际成本 图 10 是不同日均需求下的成本堆叠:蓝色卡费恒定 199 元,红色超次费在 2.3 次/日之后开始出现,3.0 次/日时已到 35 元。右轴阶梯是边际成本:60 次以内 3.32 元/次(199 除以 60),越线后 2.0 元/次。边际成本从 3.32 元掉到 2 元,这是「越用越便宜」的配额经济,也是月卡的商业逻辑:先收 199 元的底,再用低价超次留住高频用户。

5 结论

  1. 月卡 60 次不够,但只差 2 次,买第二张卡是错的。 本案 62 次、成本 203 元;两张卡 398 元、多付 195 元(图 3)。第二张卡的配额只有 60 次,最多省 120 元,追不平 199 元的卡费。
  2. 临界条件不是 99.5 次,是超次单价 3.32 元/次。 「199 除以 2」的算法漏了第二张卡也限 60 次;正确的比较是 \(199/60\)(式 6)。在 2 元/次的价目下,双卡在 120 次以内永不划算(图 1)。
  3. 真正的对照是「按次 4.5 元」。 60 次按次要 270.0 元,月卡 199 元,等于把单次成本从 4.5 元压到 3.3 元;需求低于 44 次时按次更省(图 1 的第一个交点),高于 44 次就该买卡。
  4. 日粒度是伪自由度,风险才是真变量。 目标只依赖 \(\sum_t k_t\),26 个整数变量怎么摊都不改最优值(式 2);但把需求当随机量后,爆表概率 57%、期望超次 4.22 次、期望成本 207.4 元(图 9)——预算要按 207.4 元做,不能按 203 元做。
  5. 配额的商业逻辑是「低边际成本 + 高固定费」。 边际成本在 60 次处从 3.32 元跌到 2.0 元(图 10),越线反而更便宜;月卡赚的是那 199 元的底,超次只是不让人跑掉的护栏。对骑手的启示:把换电次数稳定在 60 次以内,比纠结超次单价更值钱(图 6 整行只差 0 元)。

参考文献

[1] Gurobi Optimization LLC. Gurobi Optimizer Reference Manual[Z]. 2024.

[2] Kellerer H, Pferschy U, Pisinger D. Knapsack Problems[M]. Berlin: Springer, 2004.

[3] Martello S, Toth P. Knapsack Problems: Algorithms and Computer Implementations[M]. Chichester: John Wiley & Sons, 1990.

[4] 司守奎, 孙玺菁. 数学建模算法与应用[M]. 3 版. 北京: 国防工业出版社, 2021.

复现方式:python batch_071.py;数据与结果见同目录 .csv / .json,图见 figs/

posted @ 2026-11-11 18:04  小青蛙电气  阅读(2)  评论(0)    收藏  举报