案例074 30/40/50 单的阶梯奖

案例074 30/40/50 单的阶梯奖

摘要:日单量 30 单奖 25 元、40 单奖 60 元、50 单奖 120 元,取最高档不叠加。当日已跑 34 单,剩余 3 h 只能再跑 12 单,上限 46 单。三档奖金写成增量形式 \(25z_1+35z_2+60z_3\) 并配 \(z_1\ge z_2\ge z_3\),Gurobi 给出补跑 6 单、共 40 单的最优解:拿 40 档 60 元,当日增量收益 53.30 元,比稳在 34 单多 28.30 元。50 档需 50 单,比上限多 4 单,结构性不可达。若直接写 \(25z_1+60z_2+120z_3\) 且不做互斥,同一方案被算成 78.3 元,虚高 25 元。

关键词:阶梯奖励;增量建模;互斥约束;混合整数规划;临界分析

1 问题提出

1.1 今天还差多少单

平台的冲单奖是阶梯式的:跑满 30 单给 25 元,40 单给 60 元,50 单给 120 元,只取最高一档,不叠加。外卖小哥此刻已送 34 单——30 档其实已经到手,白拿 25 元。剩下三小时,路况熟的情况下最多再跑 12 单,天花板 46 单。于是问题只剩一句:还跑不跑,跑到哪一档?

跑 6 单够 40 档,多拿 35 元;跑 16 单够 50 档,再多拿 60 元——第二件事今天已经不可能。而表格里 12 张候选单的净收益差别极大:近单 6 元上下,远单从第 7 单起就倒贴。

表 1 剩余 3 h 的候选订单(净收益 = 毛收入 − 远单折价)

| 订单 | 距离/km | 用时/min | 毛收入/元 | 折价/元 | 净收益/元 | 入选 | |---|---|---|---|---|---|---| | R01 | 1.2 | 12 | 9.0 | 2.6 | 6.40 | ✓ | | R02 | 1.6 | 13 | 9.2 | 3.1 | 6.10 | ✓ | | R03 | 2.0 | 13 | 9.1 | 3.3 | 5.80 | ✓ | | R04 | 2.3 | 14 | 9.0 | 3.6 | 5.40 | ✓ | | R05 | 2.8 | 14 | 8.8 | 3.8 | 5.00 | ✓ | | R06 | 3.1 | 15 | 8.6 | 4.0 | 4.60 | ✓ | | F07 | 4.2 | 15 | 8.4 | 8.6 | -0.20 | | | F07—F12 | 4.2—7.2 | 15—17 | 7.4—8.4 | 8.6—11.2 | -0.20…-3.80 | |

1.2 三条为什么要算

第一,拿几档不等于加几档奖金:阶梯奖是累积值,把三档直接相加会把低档的钱再数一遍;第二,够不够得着要算时间账:50 档还差 16 单,3 h 只装得下 12 单;第三,冲刺本身有成本:多干三小时要付体力、油耗和晚饭,还得接一串净收益为负的远单。这三条分别对应奖金系数、门槛约束和目标里的 \(F y\)。

1.3 Gurobi 怎么解

12 个选单 0-1 变量、3 个档位变量、1 个开工变量,共 16 个 0-1 变量,约束 19 条,分支定界 0.01 秒收敛;真正耗时的是扫描:全案求解 45 个 MILP,共 1.6 秒。

2 数学模型

\(x_i\in\{0,1\}\) 表示是否接第 \(i\) 单(\(i=1,\dots,12\)),\(v_i\) 为其净收益;\(z_1,z_2,z_3\in\{0,1\}\) 表示是否达到 30/40/50 档;\(y\in\{0,1\}\) 表示是否继续干三小时;\(t_i\) 为用时,\(F\) 为三小时机会成本,\(N_0=34\) 为已跑单量。

2.2 目标函数(增量形式)

三档奖金 25、60、120 元是累计值,相邻两档之差才是新到手的钱:25、35、60 元。目标必须按增量写:

\[\max\;\sum_{i=1}^{12} v_i x_i + 25 z_1 + 35 z_2 + 60 z_3 - F y \tag{1} \]

系数 \(25,35,60\) 都是“从零到该档”的累计额,因此必须配单调约束;否则 \(z_2=1\) 而 \(z_1=0\) 这种跳档领取会凭空多出 35 元。

2.3 约束条件

档位与单量的联动写成一条门槛递增的式子,每上一档右端加 10:

\[\sum_{i=1}^{12} x_i + 34 \;\ge\; 30 z_1 + 10 z_2 + 10 z_3 \tag{2} \]

\(z_3=1\) 时右端 \(=50\);\(z_1=z_2=1,z_3=0\) 时右端 \(=40\)。再补单调、工时与开工联动:

\[z_1 \ge z_2 \ge z_3 \tag{3} \]

\[\sum_{i=1}^{12} t_i x_i \le 180,\qquad x_i \le y \tag{4} \]

式 (3) 是增量写法的开关:够 40 档必然够 30 档。式 (4) 把三小时折成 180 分钟,候选单合计 177 分钟刚好卡满;\(F\) 只在 \(y=1\) 时出现一次,不按单摊。

2.4 两种替代写法与它们的毛病

写法甲(错误):保留原档金额、只加单调约束——

\[\max\;\sum_i v_i x_i + 25 z_1 + 60 z_2 + 120 z_3 \tag{5} \]

够 40 档时 \(z_1=z_2=1\),奖金被算成 \(25+60=85\) 元而真实只有 60 元,重复计了 25 元;若 50 档可达更糟:\(25+60+120=205\) 元对 120 元,虚高 85 元。

写法乙(互斥):改回原档金额,并要求只选一档——

\[\sum_{k=1}^{3} z_k \le 1,\qquad \sum_i x_i + 34 \ge 30 z_1 + 40 z_2 + 50 z_3 \tag{6} \]

式 (6) 与式 (1)—(4) 等价(两模型最优值差 0.0e+00 元)。两种都对,但不能混:增量系数配互斥、原档金额配单调,都会算错。

3 Gurobi 求解实现

3.1 建模要点

bon = 25*z[0] + 35*z[1] + 60*z[2]          # 增量,不是 25/60/120
m.addConstr(quicksum(x) + 34 >= 30*z[0] + 10*z[1] + 10*z[2])
m.addConstr(z[0] >= z[1]); m.addConstr(z[1] >= z[2])  # 跳档保护
m.setObjective(quicksum(v[i]*x[i]) - F*y + bon, GRB.MAXIMIZE)

一条实现细节:用 \(x_i\le y\) 把开工变量和选单绑起来。若省掉 \(y\)、把 \(F\) 按单平摊,模型会认为“少跑一单就省一点成本”,从而永远选零单,结论完全相反。

表 2 四种写法的求解结果对比

| 方案 | 补单数 | 当日单量 | 档次 | 奖金/元 | 成本/元 | 净收益/元 | |---|---|---|---|---|---|---| | 稳在 34 单 | 0 | 34 | 30 档 | 25 | 0.0 | 25.00 | | 冲到 40 单(增量) | 6 | 40 | 40 档 | 60 | 40 | 53.30 | | 顶满 46 单(增量) | 12 | 46 | 40 档 | 60 | 40 | 41.10 | | 冲到 40 单(直接相加) | 6 | 40 | 40 档 | 85 | 40 | 78.30 | | 冲到 50 单 | — | 需 50 | 不可达 | — | — | — |

最优解补 6 单(前 6 个近单),单净合计 33.30 元,加 40 档奖金 60 元、扣机会成本 40 元,共 53.30 元。顶满 12 单反落到 41.10 元:后 6 单净收益合计 -12.20 元,奖金一分不多,白跑。

4 结果分析

4.1 台阶结构与方案对比

图 1 阶梯奖金曲线与增量拆解:30/40/50 三档的跳跃

图 1 是“取最高档”的真面目:三个平台、跳三次。34→40 单奖金从 25 跳到 60,增量 35 元;40→50 单再跳 60 元。图上两段双箭头正是式 (1) 里 $35z_2$ 与 $60z_3$ 的几何来源;灰区(>46 单)是今天到不了的地方。

图 2 单量—增量收益散点(气泡=该单边际净收益),标出三个断点

图 2 逐点画出 34 到 46 单的边界。34—39 单这一段整体压在零线下方:跑一单净赚 6.4 元,却要先摊 40 元班次成本,**跑了不如回家**;到 40 单被 35 元奖金一把拽到 53.3 元,这就是断点。气泡在 40 单后迅速变小变暗,边际净收益从 6.4 掉到 -3.8 元。最优解(星号)落在断点上,而非最右端。

图 3 稳在 34 单 / 冲 40 / 顶满 46 / 直接相加 四方案对比

四个柱子的排序说明一切:冲 40 单 53.3 元 > 顶满 46 单 41.1 元 > 稳在 34 单 25.0 元 > 错误写法的 78.3 元(假的)。稳与冲之差 28.3 元 = 35 元增量奖金 + 33.3 元单收入 − 40 元机会成本。顶满更差,因为第 7—12 单合计 -12.2 元,抵不过夜里三小时的体力折价。

图 4 剩余 3 h 的累计单量与 40/50 档位线

图 4 是时间轴上的账:按实际用时累加,第 96 分钟(1.6 h)越过 40 档线,此后每一单都在多跑不多拿的区间。50 档线横在 50,曲线最高只到 46,差 4 单,按平均 14.8 分钟一单还需 59 分钟,而 180 分钟已被 12 单占去 177 分钟。

4.2 灵敏度:奖金多少、成本多高才值得冲

图 5 40 档奖金 × 最优收益(双轴:补单数阶梯)

图 5 把 40 档奖金从 25 拉到 100 元:左轴最优收益,右轴补单数。补单数在 $A_2^{\ast}=31.7$ 元处从 0 跳到 6,这就是临界线——

\[A_2^{\ast} = A_1 + F - \sum_{i=1}^{6} v_i = 25 + 40 - 33.30 = 31.70\;\text{元} \tag{7} \]

读法很直白:40 档奖金的增量(\(A_2-25\))要盖住“补 6 单的机会成本减去这 6 单的净收入”。本案 \(A_2=60\) 元远高于 31.7 元,冲是稳赚;若平台把 40 档压到 31 元(增量只剩 6 元),就该收工。

图 6 可跑单量 × 40 档奖金 的最优档位热图

图 6 是二维决策地图。可跑 8~12 单时,40 档奖金 25 元只值 1 档、45 元以上才升 2 档;最末一行(16 单,约 4.3 h)几乎整行是 3 档——**多出的 4 单把 50 档从不可达变成可达**,比调奖金有效得多。唯一例外是 100 元那格掉回 2 档:此时 50 档相对 40 档的增量只剩 20 元,不值再多跑 10 单。

图 7 三小时机会成本 × 最优收益与档位(第三维)

图 7 把 $F$ 当自变量:收益曲线在 $F^{\ast}=68.3$ 元处与稳在 34 单的水平线相交,右侧档位从 2 掉回 1。本案 $F=40$ 元(每小时 13.3 元的体力与油耗),离临界还有 28.3 元余量,结论不脆弱。

图 8 单量—收益前沿与不可行阴影(50 档整块不可达)

图 8 的实线是前沿,虚线是“假如奖金恒为 25 元”的对照——两线在 40 单处的垂直落差 -5.0 元就是阶梯奖的全部价值,粉色区则是“跑了还不如回家”的地带。120 元横线从头到尾没被碰到,右侧灰区(46 单以上)整体不可行。**这就是“50 档不用算”的正式理由**:不是不划算,而是可行域里没有它。

图 9 三小时内可跑单量的分布与累积概率

图 9 承认不确定性:三小时能跑几单本身随机(按 $\lambda=11$ 的泊松到达抽 4000 次、截断在 12 单)。够 40 档(补满 6 单)的概率 96.4%,够 50 档的概率 0.0%——连抽样都撞不到。最优策略的期望奖金 58.73 元,比死守 30 档的 25 元高 33.73 元。

图 10 四方案的边际贡献堆叠:补单净收益、档次奖金与冲刺成本

图 10 把每个方案拆三层:蓝是补单净收益、黄是档次奖金、红是冲刺成本。冲 40 单是 33.3 + 60 − 40 = 53.3;顶满 46 单第二层一分没变、第一层缩到 21.1,整体矮了 12.2 元。错误写法那根最刺眼:奖金层凭空多出 25 元,**模型没错、约束没错,只是系数写错一格**。

5 结论

(1)今天的最优动作是补 6 单、够 40 档:增量收益 53.30 元,比稳在 34 单多 28.30 元。这 6 单净赚 33.30 元,加 35 元增量奖金、扣 40 元机会成本,每单边际奖励 5.83 元,接近一单的平均净收益,必须走。
(2)50 档不是“不划算”,是“不可达”:上限 46 单,差 4 单(约 59 分钟),而 3 h 已被 12 单占满。要够 50 档只能把可跑单量从 12 提到 16,靠提前开工,不能靠跑得更快。
(3)顶尖满 12 单是陷阱:第 7 单起净收益转负,合计 -12.2 元,奖金一分不多。收益曲线的峰值在 40 单,不在最右端。

(4)增量形式是核心:式 (1) 的 \(25,35,60\) 与式 (2) 的 \(30,10,10\) 必须同构——前者是台阶高度、后者是台阶位置。直接写 \(25z_1+60z_2+120z_3\) 会虚高 25 元(40 档)或 85 元(50 档);改用互斥约束 \(\sum_k z_k\le 1\) 同样正确,但不能与增量系数混用。

(5)鲁棒区间已量化:40 档奖金高于 31.7 元、三小时成本低于 68.3 元,冲 40 档就成立。本案两数是 60 元与 40 元,余量 28.3 元与 28.3 元,除非晚上下雨单量骤降,这个决定不必重算。

参考文献

[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_074.py;数据与结果见同目录 .csv / .json,图见 figs/

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