很多人第一次听到“B题题练习”这个词,第一反应是:B题是什么?为什么要专门拿来练习?这里的B题,最常见的就是数学建模竞赛里的第二道题目,像全国大学生数学建模竞赛(CUMCM)每年都会出A题、B题、C题,美赛里也有对应风格的题目类型。我个人的理解是,所谓“B题题练习”,就是围绕这类管理科学、资源配置、优化决策方向的问题,做拆分专题、反复训练的一套方法。这篇文章就把我在备赛和带比赛过程中积累的B题练习经验完整写出来,从读题、建模、求解到写作踩坑,给你一条可以直接照着走的路。
这篇内容适合三类人:一是正在备赛数学建模、还没摸清B题套路的同学;二是指导老师想带学生做专项训练,需要一套可复用的练习框架;三是工作中遇到类似“资源调度上限”“成本最小化”这类问题,想看看建模怎么落地的从业者。放心,我不会堆砌一堆理论,说的都是真实跑过流程后留下来的东西。
1. 内容整体设计与思路拆解
1.1 B题在竞赛里的定位是什么
想要练好B题,先得知道B题和其他题目差在哪。以国赛为例,A题通常偏物理、工程,题目里会给你明确的机理关系,比如热传导、受力分析、流体力学,这些东西本质上是在考“你知不知道某个物理规律”,建模的核心工作是把机理用方程写出来,再靠数值方法求解。C题更偏数据挖掘、统计分析,考的是从数据里找规律的能力。
B题不一样。B题往往是一个“管理场景”,比如工厂生产计划、物资调度、路线规划、资源分配、项目安排,甚至银行网点布局、医院排班。题目给的往往是一大段文字,你知道背景,知道要决策什么,但数学结构不会直接摆在你面前。你需要自己定义变量、自己找约束、自己定优化目标。
换句话说,B题考的是“把实际问题翻译成数学语言”的能力。这个能力跟物理直觉关系不大,跟能不能把复杂约束拆清楚关系很大。所以B题经常被大家描述成“文字题”,但恰恰是这种题,最容易在建模环节翻车——不是不会建,而是漏条件、错约束,或者目标函数定偏了。
1.2 为什么B题需要单独设计练习
很多队伍备赛的常见做法是“拿到什么题练什么题”,国赛真题、美赛真题、校赛题混着刷。这种方式不能说错,但针对性很差。B题的出题风格、模型偏好、写作要求非常稳定,值得拿出来单独练,原因有三点。
第一,B题的模型工具高度集中。优化类问题是绝对主力,常用的模型就那几类:线性规划、整数规划、多目标规划、动态规划,再配合启发式算法、仿真。把这些工具练熟,B题的基本盘就稳了。第二,B题对“写作决策建议”的要求高。建模竞赛不止看模型对不对,还要看你能不能把结果变成“人能执行”的方案,这一点在B题里特别突出。第三,B题练习能锻炼团队配合。因为B题建模工作量大,建模手、编程手、写作手必须同步进场,三个人的配合节奏直接决定成败。
所以我的建议是:不管你是第一次参赛还是已经练过几道题,都应该单独拿出一到两周做B题专项训练,而不是把B题混在一堆题目里“顺带练”。这里说的专项训练,不是把几年的B题从头到尾做一遍,而是按照“读题—建模—求解—写作—复盘”五个环节拆开来练。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心细节解析与实操要点
2.1 用“三段式读题法”把文字变成结构
拿到一道B题,题目读三遍算少的,但很多人读三遍还是脑子里一团浆糊,原因是没有带着问题去读。我自己练题和带学生时,一直用一套“三段式读题法”,效果非常稳定,具体分三步走。
第一步,读背景,找决策者。你要搞清楚这道题里“谁在做决策”,以及“他到底想干什么”。比如题目说的是“某工厂要安排下个月的生产计划”,那决策者就是工厂管理者,他想干的可能是利润最大化,也可能是成本最小化,还可能是按期交货率最高。这个“目标”就是后面目标函数的雏形。
第二步,圈约束,找限制条件。把题目里所有“不超过”“至少”“必须在……之前”“总共只有”这类词全部圈出来。B题里的约束条件往往藏在很不起眼的句子里,比如“每台设备每天最多工作16小时”后面的那半句“且切换产品需要2小时准备时间”。漏掉一个约束,轻则模型结果偏了,重则整个方案不可行。
第三步,列变量,做一张表。把所有出现过的数量、价格、时间、库存、能力全部列进一张表,标明单位和取值范围,再把它们之间的关系用一句话写出来。比如“A产品单件利润 = 售价—原料成本—加工成本—包装成本”。这张表就是你建模型时的“素材库”,哪里缺变量、哪里约束不够,一眼就能看出来。
2.2 B题的题型判断与模型选型
练B题练到一定量之后,你会发现题目虽然讲的故事五花八门,但背后的模型骨架是可以归类的。我按出现频率从高到低排一下,帮你建立一套“看到关键词就能反应出模型”的能力。
第一类是资源配置与生产计划类,关键词是“最大化利润”“最小化成本”“产量决策”“排产计划”,对应线性规划、整数规划。第二类是路径规划与物流调度类,关键词是“最短路径”“车辆调度”“配送路线”“最晚到达时间”,对应图论算法、动态规划以及遗传算法等启发式方法。第三类是综合评价与排序类,关键词是“排序”“评价”“权重”“优先选择”,对应层次分析法、熵权法、TOPSIS等评价模型。第四类是预测类,关键词是“未来趋势”“需求量预测”“市场价格预测”,对应回归分析、时间序列模型。
这里要特别说一点:一个B题往往不是单一模型解决到底的,更多时候是“评价 + 优化”的组合,或者“预测 + 优化”的组合。比如题目先让你预测未来一周的需求量,再让你制定生产计划,那这道题本质上就是“预测 + 优化”,两头都不能偏。练题时不要只盯着自己熟悉的模型,要有意识地训练“多模型串联”的能力。
3. 实操过程与核心环节实现
3.1 从一道简化B题看完整流程
为了看清楚B题练习到底怎么落地,我拿一道我平时训练用的简化题来走一遍完整流程。这道题是刻意设计的,规模不大,但含了B题最常见的核心要素。
题目背景:某工厂有两条生产线,生产两种产品P1和P2。P1的单件利润是40元,P2的单件利润是30元。P1在生产线1上的加工时间是2小时/件,在生产线2上的加工时间是1小时/件;P2在生产线1上加工1小时/件,在生产线2上加工2小时/件。生产线1每周可用工时为80小时,生产线2每周可用工时为60小时。另外,由于原料供应限制,P1每周最多生产30件,P2每周最多生产20件。市场要求P1每周至少生产15件,否则会丢掉长期客户。问:工厂每周应分别生产多少件P1和P2,才能使总利润最大?
这道题看起来很简单,但它把B题里最典型的“目标函数 + 线性约束 + 变量上下限”都打包在一起了。拿来练手特别合适,很多国赛B题的简化版就是这类结构。
3.2 从题目到数学模型的三步翻译
拿到这道题,按刚才说的三段式读题法先走一遍。决策者是工厂管理者,目标是总利润最大化;约束有两条生产线的工时限制、原料供应限制、市场需求限制;变量只有P1和P2的周产量,设为x1和x2。
第一步写目标函数:利润 = 40x1 + 30x2,所以 max Z = 40x1 + 30x2。
第二步写约束条件。生产线1的工时约束是2x1 + x2 ≤ 80;生产线2的工时约束是x1 + 2x2 ≤ 60;原料限制是x1 ≤ 30,x2 ≤ 20;市场需求约束是x1 ≥ 15。再加上变量非负约束x1 ≥ 0,x2 ≥ 0。这里市场约束其实就是x1的下限,你可以直接当它是一个约束条件,也可以归到变量取值范围里,本质一样。
第三步,检查模型结构。目标函数是线性的,约束都是线性的,决策变量是连续变量,这就是一个标准的线性规划问题。用图解法可以手算,用求解器可以瞬时出结果。我强调一下,练习初期一定要养成“三步翻译”的习惯:先写目标函数,再写约束条件,最后检查变量取值。这个顺序乱了,后面很容易丢条件。
3.3 用Python求解并解读结果
线性规划的求解,在Python里最常用的库是scipy.optimize的linprog,也可以用pulp或者ortools,这几款工具都很成熟。我个人习惯是练习阶段用linprog,因为不需要额外安装依赖,环境要求低;论文阶段如果涉及整数规划,就换pulp或者ortools,因为linprog本身不支持整数约束。
下面是这道题的求解代码,我注释写得很详细,可以直接照着跑。
python复制import numpy as np
from scipy.optimize import linprog
# 目标函数系数:linprog默认求解最小值,所以利润取负
c = [-40, -30] # 对应 max(40x1 + 30x2)
# 不等式约束矩阵 A_ub @ x <= b_ub
A_ub = [
[2, 1], # 生产线1工时约束:2x1 + x2 <= 80
[1, 2] # 生产线2工时约束:x1 + 2x2 <= 60
]
b_ub = [80, 60]
# 变量取值范围:x1, x2 >= 0, 同时 x1 <= 30, x2 <= 20, x1 >= 15
bounds = [(15, 30), (0, 20)] # (下限, 上限)
# 求解
result = linprog(c, A_ub=A_ub, b_ub=b_ub, bounds=bounds, method='highs')
# 输出结果
if result.success:
print("求解成功")
print("x1 (P1产量):", round(result.x[0], 2))
print("x2 (P2产量):", round(result.x[1], 2))
print("最大利润:", round(-result.fun, 2))
else:
print("求解失败:", result.message)
跑完结果就会发现,最优解是x1=20件,x2=20件,此时最大利润是1400元。你可以在心里快速验证一下:生产线1耗时2×20+1×20=60小时,没有超过80小时;生产线2耗时1×20+2×20=60小时,刚好卡满;市场要求P1至少15件、最多30件,20件都在范围内。这个结果本身没问题,但更有价值的分析其实在后面——灵敏度分析。
如果你只想拿到最优数值,上面的代码就够了;但B题要的是“方案 + 分析 + 建议”,所以必须回答“如果某个参数变了,方案该怎么调”。比如生产线2的可用工时从60变成50,最优解会怎么变?这就要看linprog输出的影子价格(shadow price),它告诉你每增加1单位某约束的资源,目标函数能提高多少。这道题里生产线2的工时已经被完全用满,所以它是有“影子价格”的;生产线1还剩20小时余量,它对应的影子价格就是0。这个信息翻译成人话就是:工厂如果想让利润进一步上升,优先扩生产线2的产能,而不是生产线1。
这就是B题练习的关键动作:不仅要会算,还要能把求解器的输出翻译成“管理建议”。很多队伍练题时跑出最优解就收工了,没有做敏感性分析,也没有把结果转成方案建议,这在比赛里会被扣掉很大一部分分。
3.4 论文写作里的关键动作
很多人觉得B题论文写作就是“把模型写出来 + 贴结果”,这个理解是错的。真正拿高分的B题论文,摘要、模型假设、求解结果、方案建议四个板块之间必须串成一条清晰的逻辑链。我按照我自己写论文的习惯,把每个板块的写作要点拆开讲。
先讲摘要。B题摘要的基本结构是:一句话交代问题背景和目标,一句话说清楚你用了什么模型,两句话概括关键求解结果,最后一句给出明确的方案建议。大致是“针对某工厂生产计划优化问题,本文构建了以总利润最大化为目标的线性规划模型,综合考虑工时、原料及需求约束,利用单纯形法求解得到P1和P2最优产量分别为20件和20件,对应最大利润1400元。结果表明,在现有资源约束下,工厂应优先释放生产线2产能以进一步提升利润。”这段话没有任何废话,信息密度极高,评审一眼就知道你做了什么、结果是什么。
再讲模型假设。B题最怕“过度假设”,有些队伍为了简化问题,直接把关键约束假设掉,比如“假设生产过程中不存在设备故障”“假设原料供应稳定”,这种假设对结果影响不大时OK,但如果题目本身就给了“原料有上限”这个条件,你再“假设原料供应不受限”,那就是自己给自己挖坑。我建议模型假设只写两类:一类是对问题边界做必要限定,比如“不考虑机器维修时间”;另一类是数据方面的说明,比如“所有价格在计划周期内保持不变”。不要乱写假设。
最后是方案建议。很多队伍论文写到最后,只给出“x1=20,x2=20”这种干巴巴的数字,没有把结果转成管理语言。我会在论文里专门加一个“建议实施方案”,把数值翻译成可执行的句子,比如“建议P1产品周产量维持在20件,P2产品周产量维持在20件;若可增加生产线2每周工作时长5小时,预计可新增利润XX元”。这种表达才是B题评审期待看到的东西。
4. 常见问题与排查技巧实录
4.1 建模阶段最容易漏的三种约束
练B题这几年,我自己踩坑加看学生踩坑,总结出建模阶段最高频的三个翻车点,你可以对照着自己检查。
第一是“隐性产能约束”。题目说“设备每周最多运行120小时”,很多人就把这个当成唯一产能约束,但题目下面还有一句“每次换产需要3小时准备时间”,这句话被当成背景信息忽略了。结果模型求解出的方案需要多次换产,实际工时根本不够用。解法很简单:读题时把所有“时间”“准备”“等待”“休息”相关词全部圈出来,追问一句“这个时间要不要占用总工时”。
第二是“变量之间的耦合约束”。很多B题里,不是每个变量都独立,而是几个变量之间互相牵制。比如“P1和P2共用同一种原料,该原料每周期货不超过50单位”,那么约束应该写成两者用量之和≤50,而不是P1≤50且P2≤50。这种耦合约束一旦漏掉,结果会严重偏乐观。
第三是“整数约束”。生产计划里“件数”天然是整数,如果你用线性规划把x1解成17.4件,方案根本没法落地。我在训练中要求学生第一轮求解先跑线性规划“估算框架”,第二轮必须把整数约束加回去再跑,然后对比两轮结果的差异。这个对比过程本身就可以写进论文的“讨论与分析”里。
4.2 模型求解出问题怎么排查
求解阶段最常见的报错就是“infeasible”(无可行解)和“unbounded”(无界解)。我每次遇到这类报错,都会按下面的顺序排查,基本五步内定位问题。
第一步,回查变量边界。你的变量上下限写反了没有?比如bounds里写的是(30, 15),下限在上限之上,那一定无解。第二步,检查约束方向。A_ub里写的是“≤”,如果你把“≥”也放进来了,那约束矩阵方向就反了。一个检查技巧是:把某个变量设为0、另一个设为一个较大的数,看约束是否还成立,用手算验证一遍。第三步,检查单位统一。这是B题特别容易翻车的地方,题目里工时可能是“分钟”而产能是“小时”,不换算直接建模型,结果差一个数量级。第四步,看求解器给出的message。linprog的返回信息里会有关键线索,比如“The problem is infeasible”,那基本就是约束自相矛盾了,去查约束系数有没有抄错。第五步,如果还是查不出来,就做一个“逐约束测试”:只保留目标函数和某一个约束,求解一遍;再增加下一个约束,逐步加。哪个约束加进去之后无解,问题就出在哪个约束上。
这个方法我强烈建议每个备赛队伍练一次。因为比赛时一旦模型无解,整个团队会非常慌,而逐约束测试是效率最高的排查路径。
4.3 论文写作里的结果不一致问题
B题论文里还有一个特别常见的扣分项:摘要写的数值和正文表格对不上。经常是摘要写“最大利润1400元”,正文表格里却显示1350元;或前面模型假设了“不考虑库存”,后面方案建议里却出现了“建议增加库存”。这些看起来是小问题,但在评审眼里就是“团队内部没有核对”,印象分大打折扣。
我带的队伍,论文写完后,专门有一个人负责“数据一致性检查”。他拿着计算器一个个核对:摘要里的每个数字在正文里有没有出处;正文每个表格的数值和模型输出的原始结果一不一致;所有建议方案有没有对应的数值支撑。这个人的角色可以是写作手,也可以是建模手,但一定不能是编程手——因为编程手看自己跑出来的结果,容易“自带滤镜”,看不出问题。
4.4 时间分配的实战建议
B题的75小时,最怕前48小时还在反复改模型,最后一天赶论文。我推荐一个比较稳的时间分配方案,按“练题时假装这就是正式比赛”的原则执行。
第一天上午:读完题,列出决策者、目标、约束、变量表,确定题型,完成第一版模型的大致框架。第一天下午:建模手和编程手同步进场,建模手完善约束细节,编程手开始写求解代码,写作手可以先搭论文的框架结构,把摘要留空。第一天晚上之前:必须跑出第一版结果,哪怕结果是错的,也应该有一条完整的“输入—模型—输出”链。第二天:专门做模型验证和灵敏度分析,看看参数微调后结果怎么变,这部分内容要写进论文。第三天:写作手主导狂写论文,建模手和编程手配合补材料、检查数据一致性、画图、排版。第三天晚上:全队通读论文,修正表述。
这个节奏的核心思路是“第一天就必须有结果”,因为B题的时间大头不是求解,而是分析和写作。
5. 练习之后怎么复盘与进阶
5.1 每次练完B题,先回答四个问题
练题不是为了练而练,每一道题练完之后必须做复盘。我的复盘模板就四个问题,每次都会带着队伍对着回答。
第一个问题:读题花了多久,卡在哪一步?如果你读题花了3小时,且卡在“变量之间的关系理不清”,那说明三段式读题法还没内化,下一道题要刻意做“变量表”。第二个问题:从题目到数学模型,哪一步最费劲?是目标函数不确定,还是约束条件写不齐,还是变量定义模糊?这一步直接指出现阶段的短板。第三个问题:求解结果是否合理?有没有做灵敏度分析?很多队伍练题只做到“跑出最优解”,这不叫完整建模,只能叫“把问题算完了”。第四个问题:建议方案是否可执行?把你的建议拿给一个不了解这个题目的人看,他能直接照着做吗?如果不能,说明写作还没到位。
四个问题回答完,你会很清楚队伍当下的弱点集中在哪个环节。下一道题就重点练那个环节,而不是从头到尾再来一遍。
5.2 训练题库怎么选、怎么排优先级
B题专项练习,优先做的就是历年国赛的B题,因为出题风格最稳定。我按难度和训练价值排一个优先顺序,供你参考。
首推做近五年的国赛B题。这些题目的数据完整度、题目结构、评分标准都很清晰,适合完整走流程。然后是美赛的MCM/ICM题目里的D题(运筹学/网络科学)和E题(环境科学),因为它们也偏优化决策方向,但英文题读起来会额外训练你的信息提取能力。如果时间充裕,校内赛或网上流传的“模拟题”也可以做,但优先级要放低,因为很多模拟题的题目质量参差不齐,可能把B题的边界条件设计得很飘,不利于训练。
另外,练习时我建议用“二八原则”:80%的时间用来做完整练习(完整跑完读题、建模、求解、写作),20%的时间做局部练习(只练读题建模、或者只练灵敏度分析)。
5.3 团队配合怎么训练
B题练习不是三个人的作业拼盘,而是三个人一起解决一个问题。常见的坑是建模手把模型建完,丢给编程手去实现,编程手跑出结果再丢给写作手,最后写出来的论文千疮百孔。正确的姿势是三个人从一开始就一起工作。
我每次训练都要求“三人同桌建模型”——也就是说,在列变量表、写目标函数、画约束的时候,三个人都必须在场。建模手负责提解法思路,编程手负责在旁边评估这个模型好不好实现,写作手负责记录过程中每一轮的假设和调整理由,这些记录后面可以直接变成论文里的“建模思路”段落。这个习惯还有个额外好处:写作手不是在论文阶段才理解模型,而是在模型诞生过程中全程参与,写出来的文字自然更准确、更顺滑。
6. 再说一点我自己练B题的体会
这几年我指导过很多支队伍练B题,也亲眼看到很多队伍从“拿到题手足无措”到“三个小时稳定产出第一版模型”。如果让我总结B题练习的核心价值,我不会说“多刷题”,而会说“建立起一套从文字到数学再到方案的转换系统”。
练B题和做数学题完全不一样,它没有一个标准答案,但有一个标准的动作链条:读懂文字、提炼变量、构建约束、求解分析、形成建议。这五个环节每一个都能拆开单独练,练熟之后再拼在一起,比赛时就不会慌。
最后再分享一个小习惯:每练完一道B题,把题目文件、模型代码、求解结果、论文终版、复盘记录放在同一个文件夹里,命名格式为“日期_题目关键词_完整/局部”。赛前一周不看新题,就翻这些文件夹,把每道题的目标函数、约束结构、求解工具、踩过的坑过一遍。这个习惯比临时抱佛脚刷十道题都管用,你可以试试。
