
简介面向2024年全国大学生数学建模竞赛B题生产过程中的决策问题参赛者的一套完整备赛资料包覆盖从建模思路、算法设计、代码实现到论文撰写的全流程。内容按问题一至问题四拆分主代码以Matlab为主同时提供Python版本便于不同编程习惯的选手直接运行与二次修改文档部分包含参考论文、降重指南和思路说明配套结果Excel表、流程PPT和结果图可帮助对照题目逐步复现实验、核验数据并完善参赛文本。资源共69个文件含27个m脚本、8个py脚本、15个txt说明、7个docx文档、5个xlsx表格、5张png图片、1个pptx和1个pdf压缩包大小仅9.48MB目录按最终版、单问版和代码/文档分类检索定位方便。截至目前已有1652人学习使用适合正在紧张备赛并希望在编程实现与论文表达上少走弯路的本科生和研究生。 2024年国赛B题“生产过程中的决策问题”一战结束之后很多队伍复盘时都感叹题目看起来只是“要不要检测、要不要拆解”的几行字真正动手才发现统计检验、期望成本、组合优化全部纠缠在一起。我今年带队完整做完了这道题从抽样方案设计到多工序产线决策再到最后一版论文和配套Python代码整个过程踩了不少坑也在反复比对中把模型的逻辑理顺了。这篇文章就把我的完整思路、代码实现和论文组织方式一次性讲清楚包含可以直接复现的关键函数和“为什么这么设计”的解释给后面备赛国赛的同学一份少走弯路的参考。无论你是刚接触数学建模还是正在为B题的“看似简单、实则烧脑”发愁这篇内容都值得你从头到尾读一遍。1. 先看明白B题到底在考什么1.1 为什么B题是“统计决策题”而不是“优化题”很多队伍拿到B题第一反应是“这不就是线性规划吗”于是急着去建整数规划模型甚至有人直接上遗传算法。这是今年最大的误区之一。B题的全称是“生产过程中的决策问题”核心场景是一家企业采购零配件经过检测、装配、成品检测等多道工序最终把产品卖给市场。现在已知每个环节的次品率、各项成本采购价、检测成本、装配成本、市场售价、调换损失等题目要你回答一批零配件到底要不要接收用什么样的抽样方案来判断各个工序要不要设置检测点检测出来的不合格品是报废、退回还是拆解回收整条产线如何组合决策才能让单位产品的期望总成本最低这些问题的本质是在有限信息、有限成本约束下做“是与否”的决策而非求一个连续变量的最优解。你当然可以把它写成0-1整数规划但真正清晰的解法是先算清楚每种决策对应的期望成本再按最小成本原则选出方案。越是这种“翻译成概率计算”的题越考验建模者对统计推断和决策树的理解深度而不是算法的炫技程度。1.2 决策链路的统一抽象我在做题时做了一件事让整个B题的模型一下子清晰起来把题目中的所有环节抽象成一条统一的决策链路。每个零配件或者半成品进入某个工序时都有一个“流入次品率”我们面临两个选择——检测或不检测。如果检测需要支付检测成本同时可能把部分次品拦截下来不检测则次品直接流入下一环节。装配后得到成品同样面临“成品检测”的选择不合格成品流入市场会造成调换赔偿也可以选择拆解回收。到底选哪条路取决于每条路的“期望成本”孰高孰低。把链路画出来之后你会发现B题所有小问都在做同一件事对每个决策节点计算“检测/不检测”“拆解/报废”等备选方案的期望成本然后选最小值。第一问的抽样检验方案本质上也是在“检测成本”和“误判风险”之间做平衡。后面的多工序扩展只是把这种单节点的比较串成了一整条链路的组合选择。2. 抽样检验用最少的样件守住置信度2.1 把“是否超过标称次品率”翻译成假设检验B题第一问通常是某零配件声称次品率不超过某个标称值比如10%企业需要设计一个抽样方案用尽量少的抽样件数判断一批货是否达标。这里的核心是企业不可能全检只能抽一部分但又要保证“误判”概率可控。我当时直接把它建模成单侧假设检验。设这批零配件的真实次品率为p标称上限为p0原假设H0p ≤ p0认为这批货合格备择假设H1p p0认为这批货不合格抽样方案由两个数决定抽样数n、接收数c。抽n件检验如果次品数d ≤ c则接收这批货如果d c则拒收。接下来要解决的问题是n和c怎么定这里必须引入两类风险。第一类风险是“货本身合格却被我们拒收”这会伤害供货方第二类风险是“货本身不合格却被我们接收”这会让次品流入生产线。题目通常会给出或暗示一个置信度要求比如“以95%的把握做出判断”这时候就要让两类错误概率都控制在一个可接受的水平内。2.2 最小样本量的遍历求解抽样方案的计算我推荐直接用二项分布的精确概率不要用正态近似去糊弄。原因后面会讲。如果检验是放回抽样或者批量足够大抽到次品的次数X服从二项分布X ~ B(n, p)。那么在p p0这个临界情况下出现“d ≤ c”的概率是P(X ≤ c) Σ_{k0}^{c} C(n,k) p0^k (1-p0)^(n-k)。我们通常要求这个概率足够大比如至少0.9或0.95同时还要控制“当p比p0高一定幅度时接收概率足够小”。具体做法是写两层循环外层遍历n内层遍历c对每一组(n,c)计算两个概率找到满足风险约束的最小n。由于n和c的搜索空间很小Python跑起来是瞬间的事。代码框架大概是这样的from scipy.stats import binom def find_sampling_plan(p0, alpha, beta, delta0.05, max_n500): # alpha: 第一类风险上限拒收合格批的概率 # beta: 第二类风险上限接收不合格批的概率 # delta: 认为“显著超标”的次品率增量 p1 p0 delta # 备择假设下的次品率 best None for n in range(1, max_n 1): for c in range(0, n 1): # 当 p p0 时接收概率应 1 - alpha prob_accept_p0 binom.cdf(c, n, p0) # 当 p p1 时接收概率应 beta prob_accept_p1 binom.cdf(c, n, p1) if prob_accept_p0 1 - alpha and prob_accept_p1 beta: if best is None or n best[0]: best (n, c) break # 同一n下c越小越好找到就跳出内层 if best is not None: break return best用这种方式第一问能得到一个很干净的结论比如“抽检n件若次品数不超过c件则接收否则退回”。这一步是整个B题最像“标准答案”的地方也是评阅老师最先看的部分务必算准确。2.3 两类风险的控制与边界条件这里有个很容易被忽略的坑题目给的是“标称次品率”但实际次品率可能更高不能只把p固定在p0上算一遍就完事。为了防止“刚好卡线”的情况我习惯在备择假设里取一个比p0略大的值比如p0 0.05甚至p0 0.1来代表“明显不合格”的状态。这样设计出来的抽样方案才有区分度。另一个边界问题是抽样方式。如果题目说的是“从一批零配件中随机抽取若干件”而且批量不大严格来说应该用超几何分布而不是二项分布。不过当批量远大于抽样数时二项分布是很好的近似。我在论文里写的是先假设批量足够大用二项分布建模然后在灵敏度分析中补充说明若批量较小可以替换为超几何分布并验证结果差异不大。这样既严谨又不给自己找太多计算麻烦。3. 单工序与整条产线的期望成本比较3.1 成本模型怎么写才不会漏B题第二问开始进入重头戏给定各环节次品率和成本参数判断每个检测点要不要设、不合格成品要不要拆解。初学者最容易犯的错是只看“检测成本”和“次品损失”两笔账漏掉了检测本身可能存在的误判成本、被剔除合格品的损失、以及拆解后回收残值对决策的影响。我的做法是把每一件产品从“零配件采购”到“最终流入市场或被处理”的全过程拆成一条概率树。树上每条路径都有一个成本所有路径按概率加权平均就得到该决策组合下的单位期望成本。以单个零配件是否检测为例。不检测时单位期望成本 零配件采购价 次品流入后续工序造成的期望损失检测时单位期望成本 采购价 检测成本 漏检次品造成的期望损失 误检合格品被丢弃的期望损失。如果题目明确“检测准确率为100%”那后两项里误检项为0漏检项为0就退化成最简单的形式但2024年B题里有些环节的检测准确率并非100%这时必须把误判写进模型不能想当然。3.2 检测点该不该加一个简单的收益判断检测点是否值得设置本质上是在比较“检测成本”和“不检测带来的期望损失”哪个更大。我自己在实际计算时会先用一个简化公式做预判不检测的期望损失 ≈ 流入次品率 × 单件次品造成的市场/装配损失检测的期望成本增加 ≈ 单件检测成本 检测本身引入的额外损失如果前者明显大于后者加检测点基本是稳赚的如果两者接近就要仔细算因为这时结论对参数非常敏感很可能一个细微的检测准确率差异就会翻转决策。这种“先粗算再精算”的好处是你可以快速排除掉那些明显不需要检测的环节把精力集中在几个临界环节上。今年B题里有一问的参数设置恰好就落在临界区域很多队伍不加分析就全检结果期望成本反而更高。3.3 拆解决策报废还是回收取决于残值与检测成本的相对关系对于不合格成品题目通常会给出两个处理选项直接报废或者拆解回收部分零配件。拆解不是免费的需要花拆解成本但拆解后可能回收一些还有价值的零配件减少下一轮采购支出。拆解决策的判断公式也非常直观比较“单件不合格品的报废净损失”和“单件不合格品的拆解净成本”。拆解净成本 拆解成本 - 回收残值。如果拆解净成本小于报废损失那就拆否则直接报废。需要注意的是拆解后的回收件不一定都是合格的如果题目进一步要求“回收件需要重新检测才能使用”那成本模型里还要再叠加一次检测费用。我们在求解时把这种“回收—再检测—再使用”的链路也纳入了概率树避免了漏算。4. 多零配件多工序的组合爆炸与动态规划处理4.1 为什么直接枚举会炸B题后面几问会把规模扩大多种零配件、多道装配工序、每道工序都可选检测或不检测、成品可选择检测/拆解/报废。如果直接用组合枚举2的十几次方还能硬算但到几十次方就彻底跑不动了。更关键的是很多队伍即使枚举完了也没法解释“为什么这个组合最优”论文写出来缺乏说服力。我采用的方案是自底向上的动态规划。核心观察是每一道工序的决策只影响两个东西——流入本工序的次品率以及累计期望成本。至于之前的工序具体选了哪些检测方案在进入当前工序时已经凝固成“半成品次品率”这个状态。因此我们不需要保存所有历史决策路径只需要对每个可能的“输入状态”保留一个最优累计成本即可。4.2 自底向上的递归状态转移状态转移方程可以这样定义设f(i, p)表示“第i道工序之后半成品次品率为p时的最小累计期望成本”。对于第i道工序决策集合D_i包含不检测、检测、以及如果涉及成品拆解/报废等动作。对每个决策d ∈ D_i我们可以根据输入的次品率p和该工序的次品率、检测准确率推算出输出次品率p以及本工序增加的期望成本c_i(d)于是f(i, p) min over d of { f(i-1, p) c_i(d) }这里p不一定是连续变量因为当检测准确率固定时输出次品率是输入次品率的一个确定性函数。多工序从前往后递推或者从后往前倒推都可以。我用的是从前往后每进入一道工序就把当前所有可能状态更新一遍最后取成品销售环节的总成本最小值。这种写的最大好处是论文里只需要一张状态转移表、一个递推关系式就能把“多工序联动决策”讲得清清楚楚评阅老师不需要读代码也知道你在算什么。4.3 源码实现的关键函数代码层面我封装了一个统一成本计算函数输入是“当前工序参数 决策向量”输出是“输出次品率 期望成本增量”。这样无论单工序还是多工序调用逻辑完全一致。def stage_cost(in_p, params, inspect, disassembleFalse): in_p: 流入本工序的次品率 params: 包含工序次品率、检测成本、装配成本、损失成本、拆解成本、回收残值等 inspect: 本工序是否检测 disassemble: 对不合格成品是否拆解 p_manufacture params[defect_rate] # 本工序产生的次品率 out_p in_p (1 - in_p) * p_manufacture # 不考虑检测时的输出次品率 if not inspect: # 不检测只承担后续损失期望 cost params[processing_cost] out_p * params[loss_per_defect] return out_p, cost # 检测的情况 detect_cost params[detect_cost] miss_rate params.get(miss_rate, 0.0) # 漏检率 false_rate params.get(false_rate, 0.0) # 误检率 # 漏检的次品仍会流出 out_p_detected out_p * miss_rate # 误检会误杀合格品增加损失 false_kill_loss (1 - out_p) * false_rate * params[unit_value] cost params[processing_cost] detect_cost false_kill_loss if disassemble: # 对不合格品拆解回收 scrap_cost out_p * (params[scrap_loss] - params[recycle_value] params[disassemble_cost]) cost scrap_cost else: cost out_p * params[loss_per_defect] return out_p_detected, cost这个函数看起来不长但B题第三问的所有组合计算都靠它。只要把每道工序的参数填进params字典然后调用DP循环就能得到全局最优决策。注意如果题目给的“检测准确率”是综合指标而不是分开的漏检率、误检率需要先根据题意拆开否则算出来的期望成本会偏。5. 从模型到论文哪些细节决定省奖还是国奖5.1 求解结果必须与题目设问一一对应B题小问很多有的队伍模型建得漂亮但结果表没有跟题目设问一一对应评阅老师找半天找不到答案分数直接打折。我写论文时在每一问的“结果分析”小节开头都用一张表把题目要求回答的问题、我们的结论、对应的成本节约比例列出来。这样做有两个好处一是评阅老师能快速定位答案二是逼着自己检查有没有漏掉小问。表格形式大概是这样题目设问决策方案单位期望成本相比基线方案的成本变化零配件A是否检测检测xxx 元/件-xx%成品是否检测不检测xxx 元/件xx%不合格成品是否拆解拆解xxx 元/件-xx%这种表在答辩和评阅时非常加分因为它直接展示了“模型输出”和“实际问题解答”之间的对应关系。5.2 灵敏度分析与模型检验不能省B题本质上是个参数驱动的问题参数稍微调一调最优决策可能就变了。我建议至少做三个方向的灵敏度分析第一次品率变动。把各环节次品率上下浮动10%到20%看最优决策是否翻转。如果翻转说明该环节是个临界点需要在论文里重点讨论。第二检测成本变动。检测成本是决策最敏感的变量之一画出“检测成本—最优决策”的分段图能直观展示什么价格区间内该检测、什么价格区间内不该检测。第三检测准确率变动。当题目给出非100%准确率时检测准确率从90%变到99%对整体期望成本的影响有多大一定要算。我在今年B题里发现有个环节的决策在准确率95%时是“检测”97%时反而变成“不检测”这种反直觉的结论写进论文非常有价值。此外模型检验不能只写“结果合理”四个字。我用的是基线对比法把全不检测方案、全检测方案作为两个极端基线证明我们选出的方案期望成本低于两个基线并且介于两者之间说明模型没有出现逻辑矛盾。5.3 使用资源包的正确顺序最后聊聊这份“思路代码论文”资源包怎么用效率最高。我的建议是先别看论文先看代码。拿到资源包之后第一步把代码跑通改几个参数观察输出结果怎么变化。这样你能快速理解每个环节的成本模型长什么样。第二步带着“这个函数在算什么”的问题去看论文你会发现论文中的公式和代码里的函数一一对应思路很快就通了。第三步合上论文自己从头推一遍期望成本公式卡住的地方再回头查。如果你能独立把小问的答案算到和论文一致这道B题你基本就吃透了。千万不要把资源包当成“交作业模板”直接抄。国赛评阅非常看重模型的逻辑自洽性如果你的论文里出现了“代码结果与正文公式不一致”这种硬伤后果是灾难级的。我用这套方法带队伍做完2024年B题最大的体会是B题比到最后比的不是谁会用更高级的算法而是谁能把统计推断和成本计算做得无懈可击。只要把抽样的两类风险讲清楚把每条决策路径的期望成本算完整把多工序的状态转移写明白国奖并没有想象中那么远。希望这篇复盘能帮你在下一场比赛中少走弯路。本文还有配套的精品资源点击获取