🏆 本文已收录于专栏:《滚雪球学数学建模(含历年真题)》

本专栏面向数学建模竞赛学习者,系统覆盖真题解析、建模方法、算法实现、论文写作与 AI 辅助建模等核心环节。无论是建模新手,还是备战华为杯、高教社杯、华数杯、国赛、美赛 MCM/ICM 的参赛者,都能在这里找到清晰、完整、可复用的建模思路,持续更新,长期有效。

🎯 免责声明: 本文题目来源于互联网公开内容,仅供学习交流与建模方法研究,不构成竞赛指导。请遵守相关赛事规则,独立完成竞赛作品,使用本文内容所产生的后果由使用者自行承担。

🎉 专栏限时优惠中:一次订阅,永久解锁,后续内容持续更新。 欢迎点击了解 👉 查看专栏详情 👈

全文目录:

1996B题:节水洗衣机

真题展示

如下为原(真)题,展示如下:

在开始之前,我想先说几句真心话:这道1996年的老题,放在今天依然非常值得深入研究。 它看起来是一个优化问题,但背后藏着资源分配、效果评价、多目标权衡等多个建模层次。很多同学拿到这类题后第一反应是"哦,这就是个最优化,用线性规划就行"——这恰恰是最常见的建模误区。

让我们系统地把它拆开来看。

一、前言:为什么这道题值得分析?

1996年的这道节水洗衣机题,是国赛历史上少数几道"同时考察物理机理建模 + 工程优化 + 实际评价"的综合性题目之一。它的特别之处在于:

第一,它有明确的物理过程。 洗衣机的"加水—漂洗—脱水"过程是可以被数学化描述的,涉及洗涤剂浓度随轮次的变化规律。这要求建模者不能只凭"直觉",而要真正理解洗涤物理机制。

第二,它有多个决策变量。 运行几轮?每轮加多少水?总用水量是约束还是目标?这些问题相互耦合,不能单独求解。

第三,它需要评价"洗涤效果"。 什么叫"满足一定洗涤效果"?这个"效果"如何量化?这是题目中最难、也最关键的一步——在没有明确定义的情况下,建模者需要自己构建合理的评价指标。

第四,它要求对比分析。 题目最后要求对照"目前常用洗衣机的运行情况"进行评价,这意味着你的模型不能闭门造车,需要有基准对比。

正因为如此,这道题是训练综合建模能力的绝佳素材。下面我们逐步展开。

二、题目背景与现实意义

2.1 现实背景

中国是一个淡水资源相对匮乏的国家,人均淡水占有量仅为世界平均水平的约四分之一。洗衣机在家庭日常用水中占据相当大的比例,传统全自动洗衣机每次洗衣用水量约为100至150升,而其中漂洗环节消耗的水量往往占总用水量的60%以上。

传统洗衣机的漂洗策略非常粗放:固定加满水、漂洗固定次数、每次完全排干。这种策略的最大问题在于:它没有根据洗涤剂残留浓度动态调整用水策略,导致大量的水被"低效使用"——前几次漂洗已经将大部分洗涤剂稀释,后几次漂洗几乎是在做无用功。

2.2 建模的现实意义

设计一个节水洗衣机控制程序,本质上是一个资源分配优化问题:在保证洗涤效果(洗涤剂残留浓度低于某阈值)的前提下,使总用水量最小化。

这道题的建模意义远不止于洗衣机本身:

  • 它代表了一类"过程优化"问题的通用建模范式;
  • 它涉及如何将工程约束转化为数学约束;
  • 它考察如何在"效果"与"成本"之间寻找最优平衡;
  • 它要求建模者既懂物理机制,又能写出可求解的数学模型。

三、题目重述

3.1 已知条件

根据题目图片,已知条件如下:

  1. 洗衣机运行过程:放入衣物和洗涤剂后,洗衣机按以下固定流程运行:

    加水 → 漂洗 → 脱水 → 加水 → 漂洗 → 脱水 → ⋯ → 加水 → 漂洗 → 脱水 \text{加水} \to \text{漂洗} \to \text{脱水} \to \text{加水} \to \text{漂洗} \to \text{脱水} \to \cdots \to \text{加水} \to \text{漂洗} \to \text{脱水} 加水漂洗脱水加水漂洗脱水加水漂洗脱水

称一个"加水—漂洗—脱水"为运行一轮

  1. 目标:在满足一定洗涤效果的条件下,使总用水量最少。

  2. 决策变量:运行多少轮( n n n),以及每轮加入多少水( v 1 , v 2 , … , v n v_1, v_2, \ldots, v_n v1,v2,,vn)。

  3. 约束:需满足一定的洗涤效果(洗涤剂残留量低于某标准)。

3.2 待解决问题

题目要求解决以下核心问题:

问题一: 建立洗涤剂残留浓度随漂洗轮次变化的数学模型,描述洗涤过程的物理机制。

问题二: 在给定总用水量的条件下,如何分配各轮用水量,使漂洗效果最好(即最终残留浓度最低)?

问题三: 在满足一定洗涤效果标准的前提下,如何确定最优轮次数和各轮用水量,使总用水量最少?并与目前常用洗衣机的运行情况进行对比评价。

3.3 附件数据说明

本题未提供附件数据,属于纯机理建模题型。

这意味着:

  • 所有参数(如衣物吸水量、初始洗涤剂量等)需要建模者合理假设
  • 模型的物理机制需要从第一性原理出发推导;
  • 结果需要在参数合理范围内进行讨论,而非依赖特定数值。

给初学者的提示: 没有数据不代表无从下手。恰恰相反,纯机理建模题更考验你对问题本质的理解。很多同学看到"没有数据"就慌了,其实这类题目的关键是把物理过程写清楚,再从中提炼数学结构。

四、问题分析

4.1 问题一分析:浓度递推模型

核心问题: 每轮漂洗后,衣物中残留的洗涤剂浓度如何变化?

这是一个典型的浓度稀释问题,可以用递推关系来描述。

关键物理过程:

  • 漂洗前:衣物中含有一定量的洗涤剂(溶于衣物吸附的水中);
  • 加水:向洗衣桶中加入清水 v i v_i vi 升;
  • 漂洗:洗涤剂在桶内均匀混合(这是一个关键假设);
  • 脱水:甩干,衣物保留固定量的水(设为 w w w 升),其余水全部排出。

这个过程的数学本质是:每轮漂洗都是一次稀释操作,洗涤剂总量在衣物吸附水中被稀释。

4.2 问题二分析:固定总水量下的最优分配

核心问题: 给定 V t o t a l V_{total} Vtotal 升水,分成 n n n 轮,每轮用 v i v_i vi 升,如何使最终残留浓度最低?

这是一个约束优化问题

min ⁡ v 1 , v 2 , … , v n c n \min_{v_1, v_2, \ldots, v_n} c_n v1,v2,,vnmincn
s.t. ∑ i = 1 n v i = V t o t a l , v i ≥ 0 \text{s.t.} \quad \sum_{i=1}^{n} v_i = V_{total}, \quad v_i \geq 0 s.t.i=1nvi=Vtotal,vi0

问题二有一个非常优美的数学结论:在总水量固定、轮数固定的条件下,每轮用水量相等时漂洗效果最优(均值不等式的直接应用)。

这个结论非常重要,它为工程实践提供了明确的指导建议。

4.3 问题三分析:最优轮次与用水量的联合优化

核心问题: 同时优化轮次 n n n 和各轮用水量 v i v_i vi,使总水量最小,同时满足洗涤效果约束。

这是问题二的逆问题,也是整道题的核心。注意:

  • n n n 是整数变量(不能漂洗2.5轮);
  • 增加轮次会增加固定用水量(每轮加水至少需要覆盖桶底);
  • 每轮用水量有上下界约束(洗衣桶容量有限)。

4.4 各问题之间的逻辑关系

具体相关示意图绘制如下,仅供参考:

逻辑关系说明:

问题一是基础,它建立了整个模型的"核心方程"——浓度递推公式。没有这个公式,后面的优化无从谈起。问题二是在问题一的基础上求解一个有约束的最优化,并得出"等量分水"的结论。问题三将问题二的结论作为输入,进一步联合优化轮次变量。最后的对比分析则需要将模型结果与现实基准进行比较,体现建模的实用价值。

五、整体建模思路

5.1 建模路线

具体相关示意图绘制如下,仅供参考:

5.2 模型选择依据

模型 适用场景 本题理由
浓度递推模型(差分方程) 离散过程的状态演化 漂洗是离散的轮次过程,状态是洗涤剂浓度
约束最优化模型 资源分配问题 总水量有限,需要最优分配
整数规划 决策变量含整数 轮次 n n n 必须是正整数
参数灵敏度分析 检验模型稳定性 参数(如吸水量 w w w)需要假设,需检验影响

5.3 算法实现思路

  • 问题二:解析求解,利用均值不等式直接证明等量分水最优,无需数值计算。
  • 问题三:数值枚举 + 解析计算。对每个轮次 n n n(从1到N_max),代入等量分水结论,计算满足约束所需的最小总水量,再取所有 n n n 中最小总水量对应的方案。

5.4 结果验证方法

  1. 物理合理性验证:浓度应单调递减,且趋近于零;
  2. 极端情况验证 n = 1 n=1 n=1 时结果退化为简单稀释;
  3. 对比验证:与传统固定策略(每轮满桶水,固定轮次)比较;
  4. 参数灵敏度验证:改变 w w w、初始浓度等参数,观察结果变化幅度。

六、数据预处理

本题无附件数据,所有参数均来自合理假设。但我们仍需对参数进行整理和说明,这相当于"参数化预处理"。

6.1 参数合理性来源

参数 符号 假设值 依据
衣物漂洗后吸附水量 w w w 10 升 5kg衣物约吸附2L/kg
初始洗涤剂量 m 0 m_0 m0 50 g 常规洗衣粉用量
初始洗涤剂浓度 c 0 c_0 c0 m 0 / w m_0/w m0/w 由定义计算
洗涤效果标准(残留率) ϵ \epsilon ϵ 0.02(2%) 工程经验值
洗衣桶有效容量 V m a x V_{max} Vmax 40 升 家用洗衣机容量
每轮最少加水量 v m i n v_{min} vmin 5 升 确保桶内水能流动

6.2 参数敏感性预判

在没有真实数据的情况下,应预先判断哪些参数对结果影响最大:

  • w w w(吸水量) 是最关键参数。它决定了每轮漂洗的稀释倍数,对最终结果有决定性影响。
  • ϵ \epsilon ϵ(残留率阈值) 直接决定了需要多少轮漂洗。
  • 初始洗涤剂量 m 0 m_0 m0 只影响绝对浓度,不影响最优分水策略(后面将看到这一点)。

6.3 MATLAB 参数初始化

%% data_preprocess.m
% 功能:初始化模型所需的所有物理参数
% 作者:建模示例代码
% 说明:本题无附件数据,所有参数为合理假设值

function params = data_preprocess()

    % ====== 物理参数 ======
    params.w       = 10;     % 衣物吸附水量(升),关键参数
    params.m0      = 50;     % 初始洗涤剂量(克)
    params.c0      = params.m0 / params.w;  % 初始浓度(克/升)
    
    % ====== 约束参数 ======
    params.epsilon  = 0.02;  % 允许的最大残留率(即最终残留量/初始量 <= epsilon)
    params.V_max    = 40;    % 洗衣桶最大容量(升)
    params.v_min    = 5;     % 每轮最少加水量(升)
    params.n_max    = 10;    % 最大考虑轮次数
    
    % ====== 传统洗衣机参数(用于对比)======
    params.v_traditional = 40;   % 传统洗衣机每轮加满水(升)
    params.n_traditional = 3;    % 传统洗衣机固定漂洗3轮
    
    % ====== 验证参数合理性 ======
    assert(params.w > 0, '吸水量必须为正数');
    assert(params.epsilon > 0 && params.epsilon < 1, '残留率必须在(0,1)之间');
    assert(params.V_max > params.v_min, '桶容量必须大于最小加水量');
    
    fprintf('参数初始化完成:\n');
    fprintf('  初始浓度 c0 = %.2f 克/升\n', params.c0);
    fprintf('  残留率阈值 epsilon = %.2f%%\n', params.epsilon * 100);
    fprintf('  吸水量 w = %.1f 升\n', params.w);
end

代码解析:

这段代码将所有参数集中在一个函数中管理,有以下几个设计考量:

  1. 为什么要把参数单独写成函数? 因为后面的灵敏度分析需要反复修改参数,集中管理避免在多个文件中查找和修改,大大减少出错概率。

  2. 为什么用 params.w 而不是直接用全局变量? 结构体传参比全局变量更安全,避免命名冲突,在大型项目中是标准做法。

  3. assert 语句的作用是什么? 在竞赛中,加入参数合理性检验可以帮助你在调试时快速定位问题,避免因为参数设置错误导致结果离谱而浪费时间。

  4. 初学者注意: 不要把 c 0 c_0 c0 m 0 m_0 m0 混淆。 m 0 m_0 m0 是洗涤剂的总量(克), c 0 c_0 c0浓度(克/升)。后面的递推方程用哪个要统一,不能混用。

七、模型假设

模型假设是数学建模论文中最容易写得"空洞"的部分。很多同学写"假设洗涤均匀进行"这样的废话,而没有说明为什么需要这个假设,以及违反这个假设会有什么影响。

下面是本题的完整假设列表,每条都附有说明:

假设1:漂洗过程中洗涤剂在桶内均匀混合。

数学含义: 每轮漂洗结束时,桶内溶液浓度处处相等。
为什么需要: 这是浓度递推公式成立的前提。如果不均匀,则脱水后衣物中残留的浓度就不等于桶内平均浓度,递推方程无法建立。
违反后果: 若实际混合不均匀,则模型会低估残留量。

假设2:每次脱水后,衣物中保留的水量恒为 w w w 升(与加水量无关)。

数学含义: 脱水后衣物吸附水量是固定常数。
为什么需要: 实际中脱水效果与转速、时间有关,但为了建立可解析的递推方程,需要这个简化。
违反后果: w w w 随轮次变化,递推方程需修改为变系数形式。

假设3:每轮加入的水为清水(洗涤剂浓度为零)。

数学含义: 加水操作不引入新的洗涤剂。
为什么需要: 显然,漂洗阶段不应再加洗涤剂,这是物理常识的数学化。

假设4:衣物纤维不吸附洗涤剂(洗涤剂完全溶于水中)。

数学含义: 洗涤剂总量 = 浓度 × 水量,无其他吸附项。
为什么需要: 简化模型,避免引入复杂的吸附动力学。
违反后果: 若有吸附效应,实际残留量会高于模型预测值,即模型偏乐观。

假设5:洗衣机每轮的运行过程(漂洗时间、转速)相同,漂洗效率只取决于水量。

数学含义: 模型中不考虑时间维度,每轮效果完全由稀释倍数决定。

假设6:洗涤效果仅由最终漂洗结束后衣物中的洗涤剂残留率来衡量。

数学含义: 效果评价指标为 r n = m n / m 0 ≤ ϵ r_n = m_n / m_0 \leq \epsilon rn=mn/m0ϵ,其中 m n m_n mn 是第 n n n 轮后残留洗涤剂量。

八、符号说明

符号 单位 含义
n n n 无量纲(正整数) 漂洗总轮次
v i v_i vi i i i 轮加入的清水量
V V V 总用水量, V = ∑ i = 1 n v i V = \sum_{i=1}^{n} v_i V=i=1nvi
w w w 每次脱水后衣物保留的水量(常数)
m 0 m_0 m0 初始洗涤剂总量
m k m_k mk k k k 轮漂洗脱水后衣物中残留的洗涤剂量
c k c_k ck 克/升 k k k 轮漂洗过程中桶内溶液的浓度
r k r_k rk 无量纲 k k k 轮后的洗涤剂残留率, r k = m k / m 0 r_k = m_k / m_0 rk=mk/m0
ϵ \epsilon ϵ 无量纲 允许的最大残留率(洗涤效果标准)
V m a x V_{max} Vmax 洗衣桶最大容量
v m i n v_{min} vmin 每轮最少加水量
V ∗ V^* V 最优总用水量
n ∗ n^* n 正整数 最优漂洗轮次
v ∗ v^* v 最优每轮用水量(等量分水时)

九、模型一:浓度递推基础模型

9.1 模型思想

这个模型要回答一个基本问题:每轮漂洗后,衣物中残留的洗涤剂有多少?

我们来还原物理过程:

  • 漂洗前(第 k k k 轮开始前): 衣物中含有 m k − 1 m_{k-1} mk1 克洗涤剂,溶于 w w w 升水中。
  • 加水: 向桶中加入 v k v_k vk 升清水。此时桶中总水量为 w + v k w + v_k w+vk 升,洗涤剂总量仍为 m k − 1 m_{k-1} mk1 克。
  • 漂洗(均匀混合): 桶内浓度变为 c k = m k − 1 / ( w + v k ) c_k = m_{k-1} / (w + v_k) ck=mk1/(w+vk)
  • 脱水: 排出桶中水,衣物保留 w w w 升水,携带洗涤剂 m k = c k ⋅ w = m k − 1 ⋅ w / ( w + v k ) m_k = c_k \cdot w = m_{k-1} \cdot w / (w + v_k) mk=ckw=mk1w/(w+vk) 克。

9.2 数学表达式

递推方程:

m k = m k − 1 ⋅ w w + v k , k = 1 , 2 , … , n m_k = m_{k-1} \cdot \frac{w}{w + v_k}, \quad k = 1, 2, \ldots, n mk=mk1w+vkw,k=1,2,,n

其中 m 0 m_0 m0 为初始洗涤剂量(已知), w w w 为衣物保留水量(常数), v k v_k vk 为第 k k k 轮加水量(决策变量)。

展开递推:

m n = m 0 ⋅ ∏ k = 1 n w w + v k m_n = m_0 \cdot \prod_{k=1}^{n} \frac{w}{w + v_k} mn=m0k=1nw+vkw

残留率:

r n = m n m 0 = ∏ k = 1 n w w + v k r_n = \frac{m_n}{m_0} = \prod_{k=1}^{n} \frac{w}{w + v_k} rn=m0mn=k=1nw+vkw

这个公式非常重要。注意观察: r n r_n rn m 0 m_0 m0 无关! 这意味着初始洗涤剂量不影响最优分水策略,只影响是否需要更多轮次(当然, m 0 m_0 m0 越大, c 0 c_0 c0 越高,但相对残留率的表达式中 m 0 m_0 m0 已经约掉了)。

洗涤效果约束:

r n = ∏ k = 1 n w w + v k ≤ ϵ r_n = \prod_{k=1}^{n} \frac{w}{w + v_k} \leq \epsilon rn=k=1nw+vkwϵ

9.3 参数解释

  • w / ( w + v k ) w/(w+v_k) w/(w+vk) 称为第 k k k 轮的稀释因子,范围在 ( 0 , 1 ) (0,1) (0,1) 之间,表示该轮漂洗后残留比例。
  • 稀释因子越小( v k v_k vk 越大),该轮去除效果越好;
  • n n n 轮的总残留率是各轮稀释因子的乘积

9.4 求解方法

模型一本身是解析可解的,不需要数值方法。给定 v k v_k vk,直接代入公式计算即可。

9.5 MATLAB 实现

%% build_model.m
% 功能:计算给定各轮用水量下的洗涤剂残留情况
% 输入:params(参数结构体),v_vec(各轮用水量向量,单位:升)
% 输出:result(包含各轮残留量、残留率等信息的结构体)

function result = build_model(params, v_vec)

    n = length(v_vec);          % 漂洗轮次
    w = params.w;               % 衣物吸附水量
    m0 = params.m0;             % 初始洗涤剂量
    
    % 初始化存储数组
    m = zeros(1, n+1);          % m(k+1) 对应第k轮后残留量(MATLAB从1开始)
    r = zeros(1, n+1);          % 残留率
    c = zeros(1, n);            % 各轮漂洗时桶内浓度
    
    m(1) = m0;                  % 初始状态
    r(1) = 1.0;                 % 初始残留率为100%
    
    % 逐轮计算递推
    for k = 1:n
        % 检查加水量是否合理
        if v_vec(k) < params.v_min
            warning('第%d轮加水量%.2f升低于最小值%.2f升', k, v_vec(k), params.v_min);
        end
        if v_vec(k) > params.V_max
            error('第%d轮加水量%.2f升超过桶容量%.2f升', k, v_vec(k), params.V_max);
        end
        
        % 漂洗时桶内浓度(混合后)
        c(k) = m(k) / (w + v_vec(k));
        
        % 脱水后残留洗涤剂量(核心递推公式)
        m(k+1) = m(k) * w / (w + v_vec(k));
        
        % 残留率
        r(k+1) = m(k+1) / m0;
    end
    
    % 打包输出结果
    result.m       = m;         % 各轮残留量(克)
    result.r       = r;         % 各轮残留率
    result.c       = c;         % 各轮漂洗浓度(克/升)
    result.n       = n;         % 总轮次
    result.V_total = sum(v_vec);% 总用水量(升)
    result.v_vec   = v_vec;     % 各轮用水量
    result.final_r = r(end);    % 最终残留率(关键指标)
    
    % 判断是否满足洗涤效果标准
    result.is_satisfied = (result.final_r <= params.epsilon);
    
    fprintf('\n=== 漂洗过程分析 ===\n');
    fprintf('总轮次: %d轮\n', n);
    fprintf('总用水量: %.2f 升\n', result.V_total);
    fprintf('最终残留率: %.4f%%\n', result.final_r * 100);
    fprintf('是否满足洗涤标准: %s\n', mat2str(result.is_satisfied));
end

代码解析:

  1. 核心递推 m(k+1) = m(k) * w / (w + v_vec(k)) 直接对应数学模型中的 m k = m k − 1 ⋅ w / ( w + v k ) m_k = m_{k-1} \cdot w/(w+v_k) mk=mk1w/(w+vk),一行代码对应一个公式,非常清晰。

  2. 为什么数组从1开始而不是从0开始? MATLAB的数组下标从1开始,所以 m(1) 对应数学上的 m 0 m_0 m0m(k+1) 对应 m k m_k mk。这个偏移容易让初学者犯错,务必在注释中说明。

  3. 为什么要检查加水量? 竞赛中经常出现优化算法给出"离谱"的解(如负数用水量),加入检查可以快速发现问题。

  4. result.is_satisfied 的设计:将是否满足约束作为结果的一部分输出,方便后面的优化程序判断可行性。

9.6 结果分析

以传统洗衣机(每轮40升,共3轮)为例验证模型:

r 3 = ( 10 10 + 40 ) 3 = ( 1 5 ) 3 = 0.008 = 0.8 r_3 = \left(\frac{10}{10+40}\right)^3 = \left(\frac{1}{5}\right)^3 = 0.008 = 0.8% r3=(10+4010)3=(51)3=0.008=0.8

这个结果表明:传统洗衣机3轮后残留率约为0.8%,远低于我们设定的2%阈值——但它用了120升水!模型一的建立为我们接下来的优化奠定了定量基础。

十、模型二:固定总水量下的最优水量分配

10.1 基础模型的不足

模型一描述了"给定用水方案,计算漂洗结果",但没有回答"用水方案怎么定最优"。问题二要求:在总用水量 V V V 和轮次 n n n 固定的前提下,如何分配各轮用水量,使最终残留率最低?

10.2 改进思路:均值不等式的应用

优化问题形式:

min ⁡ v 1 , … , v n ∏ k = 1 n w w + v k \min_{v_1, \ldots, v_n} \prod_{k=1}^{n} \frac{w}{w + v_k} v1,,vnmink=1nw+vkw

s.t. ∑ k = 1 n v k = V , v k ≥ v m i n \text{s.t.} \quad \sum_{k=1}^{n} v_k = V, \quad v_k \geq v_{min} s.t.k=1nvk=V,vkvmin

注意:最小化 ∏ w w + v k \prod \frac{w}{w+v_k} w+vkw 等价于最大化 ∏ ( w + v k ) \prod (w+v_k) (w+vk)(因为分子是常数 w n w^n wn)。

定理(均值不等式): 对正数 x 1 , x 2 , … , x n x_1, x_2, \ldots, x_n x1,x2,,xn,若 ∑ x k = C \sum x_k = C xk=C(常数),则:

∏ k = 1 n x k ≤ ( C n ) n \prod_{k=1}^{n} x_k \leq \left(\frac{C}{n}\right)^n k=1nxk(nC)n

等号成立当且仅当 x 1 = x 2 = ⋯ = x n x_1 = x_2 = \cdots = x_n x1=x2==xn

x k = w + v k x_k = w + v_k xk=w+vk,则 ∑ x k = n w + V \sum x_k = nw + V xk=nw+V,由均值不等式:

∏ k = 1 n ( w + v k ) ≤ ( n w + V n ) n \prod_{k=1}^{n} (w + v_k) \leq \left(\frac{nw + V}{n}\right)^n k=1n(w+vk)(nnw+V)n

等号成立当且仅当 v 1 = v 2 = ⋯ = v n = V / n v_1 = v_2 = \cdots = v_n = V/n v1=v2==vn=V/n

10.3 改进模型表达式

结论:在总用水量 V V V 和轮次 n n n 固定时,各轮平均分水( v i = V / n v_i = V/n vi=V/n)使最终残留率最低:

r n ∗ = ( w w + V / n ) n r_n^* = \left(\frac{w}{w + V/n}\right)^n rn=(w+V/nw)n

这是一个极其重要的解析结论,它将 n n n 维优化问题化简为了一维问题(只需要确定 n n n V V V 的组合)。

从工程角度理解: "每轮用同样多的水"是最优策略,这与我们的直觉相符——如果某轮多用了水,另一轮少用了水,总效果反而不如平均分配。

10.4 MATLAB 实现

%% solve_model.m (模型二部分)
% 功能:在固定总水量V和轮次n下,计算最优残留率(等量分水)
% 并与不等量分配方案对比

function result2 = solve_model_fixed_V(params, V_total, n)

    w = params.w;
    
    % ====== 等量分水方案(最优)======
    v_equal = V_total / n;       % 每轮用水量相同
    
    % 验证约束
    if v_equal < params.v_min
        warning('等量分水每轮%.2f升,低于最小值,请增加总水量或减少轮次', v_equal);
    end
    if v_equal > params.V_max
        warning('等量分水每轮%.2f升,超过桶容量', v_equal);
    end
    
    % 最优残留率(解析公式)
    r_optimal = (w / (w + v_equal))^n;
    
    % ====== 不等量分水方案(对比用)======
    % 示例:前多后少,不均匀分配
    v_unequal = zeros(1, n);
    v_unequal(1) = V_total * 0.5;       % 第一轮用一半
    for k = 2:n
        v_unequal(k) = V_total * 0.5 / (n-1);  % 其余均分另一半
    end
    
    % 计算不等量方案残留率
    r_unequal = 1.0;
    for k = 1:n
        r_unequal = r_unequal * w / (w + v_unequal(k));
    end
    
    % ====== 输出结果 ======
    result2.V_total    = V_total;
    result2.n          = n;
    result2.v_equal    = v_equal;
    result2.r_optimal  = r_optimal;
    result2.v_unequal  = v_unequal;
    result2.r_unequal  = r_unequal;
    result2.improvement = (r_unequal - r_optimal) / r_unequal * 100;
    
    fprintf('\n=== 模型二:固定总水量下的最优分配 ===\n');
    fprintf('总水量: %.1f升, 轮次: %d轮\n', V_total, n);
    fprintf('等量分水:每轮%.2f升,残留率=%.4f%%\n', v_equal, r_optimal*100);
    fprintf('不均分水:残留率=%.4f%%\n', r_unequal*100);
    fprintf('等量分水改善效果: %.2f%%\n', result2.improvement);
end

代码解析:

  1. 为什么设计"不等量对比方案"? 仅仅给出"等量最优"的结论是不够的,需要用数值实验来展示"不等量有多差",这样才能让读者(和评委)信服。

  2. improvement 的计算: 这是一个非常好的习惯——计算改进幅度而不仅仅是绝对值,便于读者直观感受优化效果。

  3. 初学者注意: 上面的"不等量方案"是人为构造的,目的只是对比,不代表最优策略的竞争者。真正的最差策略(在约束范围内)需要更复杂的分析,但竞赛中通常不需要这么深入。

10.5 对比分析

w = 10 w=10 w=10L、 V = 40 V=40 V=40L、 n = 4 n=4 n=4 为例:

方案 各轮用水量 残留率
等量分水(最优) 10, 10, 10, 10 升 ( 10 / 20 ) 4 = 6.25 (10/20)^4 = 6.25% (10/20)4=6.25
前多后少 20, 6.7, 6.7, 6.7 升 约 7.8%
前少后多 2.5, 2.5, 2.5, 32.5 升 约 9.1%

等量分水明显优于其他策略,数值验证了理论结论。

十一、模型三:最优轮次与用水量的联合优化

11.1 综合建模目标

综合模型要解决的是:同时确定最优轮次 n ∗ n^* n 和最优总用水量 V ∗ V^* V,使在满足洗涤效果约束的前提下总用水量最小。

这是整道题的核心模型。

11.2 模型结构

基于模型二的结论(各轮等量分水最优),我们可以将问题化简。

决策变量: 轮次 n n n(正整数),每轮用水量 v v v(实数,等量时所有轮次相同)。

目标函数:

min ⁡ n , v V = n ⋅ v \min_{n, v} V = n \cdot v n,vminV=nv

约束条件:

( w w + v ) n ≤ ϵ (洗涤效果约束) \left(\frac{w}{w + v}\right)^n \leq \epsilon \quad \text{(洗涤效果约束)} (w+vw)nϵ(洗涤效果约束)

v m i n ≤ v ≤ V m a x (用水量约束) v_{min} \leq v \leq V_{max} \quad \text{(用水量约束)} vminvVmax(用水量约束)

n ∈ Z + , n ≤ n m a x (轮次约束) n \in \mathbb{Z}^+, \quad n \leq n_{max} \quad \text{(轮次约束)} nZ+,nnmax(轮次约束)

化简: 对于给定的 n n n,满足效果约束的最小 v v v 值为:

v m i n n e e d e d ( n ) = w ⋅ ( ϵ − 1 / n − 1 ) v_{min_needed}(n) = w \cdot \left(\epsilon^{-1/n} - 1\right) vminneeded(n)=w(ϵ1/n1)

推导过程:

( w w + v ) n = ϵ \left(\frac{w}{w+v}\right)^n = \epsilon (w+vw)n=ϵ
w w + v = ϵ 1 / n \frac{w}{w+v} = \epsilon^{1/n} w+vw=ϵ1/n
v = w ( ϵ − 1 / n − 1 ) v = w\left(\epsilon^{-1/n} - 1\right) v=w(ϵ1/n1)

此时最小总用水量为:

V ∗ ( n ) = n ⋅ v m i n n e e d e d ( n ) = n ⋅ w ⋅ ( ϵ − 1 / n − 1 ) V^*(n) = n \cdot v_{min_needed}(n) = n \cdot w \cdot \left(\epsilon^{-1/n} - 1\right) V(n)=nvminneeded(n)=nw(ϵ1/n1)

最优轮次:

n ∗ = arg ⁡ min ⁡ n ∈ 1 , 2 , … , n m a x V ∗ ( n ) n^* = \arg\min_{n \in {1, 2, \ldots, n_{max}}} V^*(n) n=argn1,2,,nmaxminV(n)

约束条件: v m i n ≤ v m i n n e e d e d ( n ) ≤ V m a x v_{min} \leq v_{min_needed}(n) \leq V_{max} vminvminneeded(n)Vmax

11.3 求解流程

具体相关示意图绘制如下,仅供参考:

流程说明:

这个枚举流程非常直观:对每个可能的轮次 n n n,计算"刚好满足效果约束"所需要的最小每轮用水量 v v v,进而得到总用水量 V ( n ) = n v V(n) = nv V(n)=nv。然后在所有可行方案中选总用水量最小的。这个方法之所以有效,是因为我们已经通过模型二证明了等量分水的最优性,将 n n n 维优化降为了一维枚举。

11.4 MATLAB 实现

%% solve_model.m (模型三主函数)
% 功能:联合优化轮次n和每轮用水量v,求最小总用水量
% 使用解析公式+枚举法

function result3 = solve_model_optimal(params)

    w       = params.w;
    epsilon = params.epsilon;
    v_min   = params.v_min;
    V_max   = params.V_max;
    n_max   = params.n_max;
    
    % 初始化存储
    V_record  = inf(1, n_max);   % 各n对应的总用水量(inf表示不可行)
    v_record  = zeros(1, n_max); % 各n对应的每轮用水量
    feasible  = false(1, n_max); % 可行性标记
    
    fprintf('\n=== 模型三:最优轮次与用水量联合优化 ===\n');
    fprintf('%-6s %-12s %-12s %-8s\n', '轮次n', '需要用水v(升)', '总水量V(升)', '可行');
    fprintf('%s\n', repmat('-', 1, 45));
    
    for n = 1:n_max
        % 由约束方程解出需要的最小每轮用水量(解析解)
        % (w/(w+v))^n = epsilon => v = w*(epsilon^(-1/n) - 1)
        v_needed = w * (epsilon^(-1/n) - 1);
        
        % 检查可行性
        if v_needed >= v_min && v_needed <= V_max
            V_total = n * v_needed;
            V_record(n)  = V_total;
            v_record(n)  = v_needed;
            feasible(n)  = true;
            fprintf('%-6d %-12.3f %-12.3f %-8s\n', n, v_needed, V_total, '✓');
        else
            fprintf('%-6d %-12.3f %-12s %-8s\n', n, v_needed, '---', '✗');
        end
    end
    
    % 找最优轮次(总用水量最小)
    if all(~feasible)
        error('在给定参数范围内无可行方案,请放宽约束');
    end
    
    [V_opt, n_opt] = min(V_record);
    v_opt = v_record(n_opt);
    
    % 验证:代入递推模型检验结果
    v_vec_opt = v_opt * ones(1, n_opt);
    result_check = build_model(params, v_vec_opt);
    
    % 计算传统洗衣机用水情况(对比基准)
    v_trad = params.v_traditional * ones(1, params.n_traditional);
    result_trad = build_model(params, v_trad);
    
    % 节水率
    water_saving = (result_trad.V_total - V_opt) / result_trad.V_total * 100;
    
    % 打包输出
    result3.n_opt         = n_opt;
    result3.v_opt         = v_opt;
    result3.V_opt         = V_opt;
    result3.final_r       = result_check.final_r;
    result3.V_record      = V_record;
    result3.v_record      = v_record;
    result3.feasible      = feasible;
    result3.result_trad   = result_trad;
    result3.water_saving  = water_saving;
    
    fprintf('\n=== 最优方案 ===\n');
    fprintf('最优轮次 n* = %d 轮\n', n_opt);
    fprintf('每轮用水量 v* = %.3f 升\n', v_opt);
    fprintf('最优总用水量 V* = %.3f 升\n', V_opt);
    fprintf('最终残留率 = %.4f%%(验证值)\n', result_check.final_r*100);
    fprintf('\n=== 与传统洗衣机对比 ===\n');
    fprintf('传统用水量: %.1f 升,残留率: %.4f%%\n', ...
            result_trad.V_total, result_trad.final_r*100);
    fprintf('节水率: %.2f%%\n', water_saving);
end

代码解析:

  1. epsilon^(-1/n) 的计算: 这对应数学推导中 ϵ − 1 / n \epsilon^{-1/n} ϵ1/n,MATLAB中直接写 epsilon^(-1/n) 即可,不需要取对数再还原。初学者有时会多此一举地写 exp(-log(epsilon)/n),虽然等价但没必要。

  2. inf(1, n_max) 初始化:inf 初始化 V_record 数组,这样 min 函数会自动忽略不可行方案(因为不可行的元素保持 inf),代码更简洁。

  3. 验证步骤: 找到最优 n ∗ n^* n v ∗ v^* v 之后,调用 build_model 重新验证结果,这是一个很好的"闭环验证"习惯。如果解析解计算有误,这一步可以发现。

  4. 传统洗衣机对比: 对比不是可选项,而是题目要求。要在代码中明确计算传统方案的各项指标,并计算节水率,这在论文中非常有说服力。

11.5 结果解释

w = 10 w=10 w=10L、 ϵ = 0.02 \epsilon=0.02 ϵ=0.02(2%残留率)为例,数值结果如下(模拟结果示例):

轮次 n n n 每轮用水量 v v v(升) 总用水量 V V V(升) 可行
1 10 ( 0.02 − 1 − 1 ) ≈ 490 10(0.02^{-1}-1) \approx 490 10(0.0211)490 490 ✗(超桶容量)
2 10 ( 0.02 − 0.5 − 1 ) ≈ 60.7 10(0.02^{-0.5}-1) \approx 60.7 10(0.020.51)60.7 121.4 ✗(超桶容量)
3 10 ( 0.02 − 1 / 3 − 1 ) ≈ 26.9 10(0.02^{-1/3}-1) \approx 26.9 10(0.021/31)26.9 80.7
4 10 ( 0.02 − 1 / 4 − 1 ) ≈ 18.1 10(0.02^{-1/4}-1) \approx 18.1 10(0.021/41)18.1 72.4
5 10 ( 0.02 − 1 / 5 − 1 ) ≈ 13.5 10(0.02^{-1/5}-1) \approx 13.5 10(0.021/51)13.5 67.5
6 10 ( 0.02 − 1 / 6 − 1 ) ≈ 10.7 10(0.02^{-1/6}-1) \approx 10.7 10(0.021/61)10.7 64.2
7 10 ( 0.02 − 1 / 7 − 1 ) ≈ 8.9 10(0.02^{-1/7}-1) \approx 8.9 10(0.021/71)8.9 62.3
8 10 ( 0.02 − 1 / 8 − 1 ) ≈ 7.6 10(0.02^{-1/8}-1) \approx 7.6 10(0.021/81)7.6 60.8
9 10 ( 0.02 − 1 / 9 − 1 ) ≈ 6.6 10(0.02^{-1/9}-1) \approx 6.6 10(0.021/91)6.6 59.4
10 10 ( 0.02 − 1 / 10 − 1 ) ≈ 5.8 10(0.02^{-1/10}-1) \approx 5.8 10(0.021/101)5.8 58.0

可以看出,随着轮次增加,总用水量单调递减(趋向一个极限值)。理论极限为:

lim ⁡ n → ∞ V ∗ ( n ) = lim ⁡ n → ∞ n ⋅ w ( ϵ − 1 / n − 1 ) = − w ln ⁡ ϵ \lim_{n \to \infty} V^*(n) = \lim_{n \to \infty} n \cdot w(\epsilon^{-1/n} - 1) = -w \ln \epsilon nlimV(n)=nlimnw(ϵ1/n1)=wlnϵ

w = 10 w=10 w=10L、 ϵ = 0.02 \epsilon=0.02 ϵ=0.02 代入: lim ⁡ = − 10 × ln ⁡ ( 0.02 ) ≈ 39.1 \lim = -10 \times \ln(0.02) \approx 39.1 lim=10×ln(0.02)39.1 升。

这个极限值有深刻的物理意义:无论怎么优化分配策略,节水洗衣机至少需要约39升水(当然,要实现这个极限需要无穷多轮,不切实际)。实际中取 n = 8 n=8 n=8 n = 10 n=10 n=10 轮已经非常接近极限,而传统洗衣机用了120升。

十二、算法流程设计

具体相关示意图绘制如下,仅供参考:

流程说明:

整个算法采用模块化设计,各函数职责清晰:

  • data_preprocess 是"配置层",只做参数初始化;
  • build_model 是"计算核心",被多处调用;
  • solve_model_* 是"优化层",在核心之上做决策;
  • plot_resultssensitivity_analysis 是"输出层",不涉及核心计算。

这种分层设计的好处是:修改参数只需改 data_preprocess,修改物理模型只需改 build_model,不会影响其他模块。

十三、MATLAB 完整代码

13.1 主程序 main.m

%% main.m
% 1996年国赛B题"节水洗衣机"完整求解程序
% 运行环境:MATLAB R2019b 及以上
% 运行方法:直接在MATLAB中运行 main.m

clc;
clear;
close all;

fprintf('====================================\n');
fprintf('  1996国赛B题:节水洗衣机 建模求解\n');
fprintf('====================================\n\n');

%% 步骤一:参数初始化
params = data_preprocess();

%% 步骤二:模型二求解(固定总水量下的最优分配验证)
fprintf('\n【模型二:验证等量分水最优性】\n');
result2 = solve_model_fixed_V(params, 60, 5);  % 示例:60升水,5轮

%% 步骤三:模型三求解(最优轮次与水量联合优化)
fprintf('\n【模型三:最优方案求解】\n');
result3 = solve_model_optimal(params);

%% 步骤四:结果可视化
fprintf('\n【生成结果图表】\n');
plot_results(params, result3);

%% 步骤五:灵敏度分析
fprintf('\n【灵敏度分析】\n');
sensitivity_analysis(params);

fprintf('\n====================================\n');
fprintf('  计算完成!请查看图表窗口。\n');
fprintf('====================================\n');

13.2 数据预处理函数(见第六节,已完整给出)

13.3 模型求解函数(见第九、十、十一节,已完整给出)

13.4 结果可视化函数

%% plot_results.m
% 功能:绘制结果可视化图表
% 图1:各轮次对应的最优总用水量
% 图2:最优方案下各轮残留率变化
% 图3:与传统洗衣机对比

function plot_results(params, result3)

    w       = params.w;
    epsilon = params.epsilon;
    n_max   = params.n_max;
    
    %% 图1:轮次 vs 最优总用水量
    figure('Name', '节水洗衣机优化结果', 'NumberTitle', 'off', ...
           'Position', [100, 100, 1200, 400]);
    
    subplot(1, 3, 1);
    n_vec    = 1:n_max;
    V_vec    = result3.V_record;
    feasible = result3.feasible;
    
    % 理论极限线
    V_limit = -w * log(epsilon);
    
    hold on;
    % 不可行点(灰色)
    plot(n_vec(~feasible), V_vec(~feasible), 'o', ...
         'Color', [0.7 0.7 0.7], 'MarkerSize', 8, 'DisplayName', '不可行方案');
    % 可行点(蓝色)
    plot(n_vec(feasible), V_vec(feasible), 'b-o', ...
         'LineWidth', 2, 'MarkerSize', 8, 'MarkerFaceColor', 'b', ...
         'DisplayName', '可行方案');
    % 最优点(红色星形)
    plot(result3.n_opt, result3.V_opt, 'r*', ...
         'MarkerSize', 15, 'LineWidth', 2, 'DisplayName', '最优方案');
    % 理论极限
    yline(V_limit, 'k--', 'LineWidth', 1.5, 'DisplayName', sprintf('理论极限 %.1f升', V_limit));
    % 传统洗衣机
    yline(result3.result_trad.V_total, 'r:', 'LineWidth', 1.5, ...
          'DisplayName', sprintf('传统洗衣机 %.0f升', result3.result_trad.V_total));
    hold off;
    
    xlabel('漂洗轮次 n');
    ylabel('最优总用水量 V* (升)');
    title('轮次 vs 最优总用水量');
    legend('Location', 'northeast');
    grid on;
    ylim([0, result3.result_trad.V_total * 1.1]);
    
    %% 图2:最优方案下各轮残留率变化
    subplot(1, 3, 2);
    v_opt_vec = result3.v_opt * ones(1, result3.n_opt);
    result_opt = build_model(params, v_opt_vec);
    
    rounds = 0:result3.n_opt;
    r_values = result_opt.r * 100;    % 转为百分比
    
    bar(rounds, r_values, 'FaceColor', [0.2 0.6 0.9], 'EdgeColor', 'none');
    hold on;
    yline(epsilon * 100, 'r--', 'LineWidth', 2, 'DisplayName', sprintf('允许阈值 %.0f%%', epsilon*100));
    plot(rounds, r_values, 'ko-', 'MarkerFaceColor', 'k', 'MarkerSize', 6);
    hold off;
    
    xlabel('漂洗轮次');
    ylabel('洗涤剂残留率 (%)');
    title(sprintf('最优方案残留率变化(n*=%d轮)', result3.n_opt));
    legend('Location', 'northeast');
    grid on;
    
    %% 图3:与传统洗衣机的对比
    subplot(1, 3, 3);
    
    categories = {'传统洗衣机', '节水洗衣机'};
    water_vals = [result3.result_trad.V_total, result3.V_opt];
    colors = [0.9 0.3 0.3; 0.3 0.7 0.3];
    
    b = bar(categorical(categories), water_vals, 'FaceColor', 'flat');
    b.CData = colors;
    
    % 添加数值标签
    for i = 1:2
        text(i, water_vals(i) + 2, sprintf('%.1f升', water_vals(i)), ...
             'HorizontalAlignment', 'center', 'FontSize', 11, 'FontWeight', 'bold');
    end
    
    ylabel('总用水量 (升)');
    title(sprintf('节水效果对比\n(节水率: %.1f%%)', result3.water_saving));
    grid on;
    ylim([0, max(water_vals) * 1.2]);
    
    % 残留率对比(右侧小标注)
    r_trad = result3.result_trad.final_r * 100;
    r_opt  = result3.final_r * 100;
    annotation('textbox', [0.75, 0.15, 0.2, 0.15], ...
               'String', sprintf('残留率比较:\n传统: %.3f%%\n节水: %.3f%%', r_trad, r_opt), ...
               'FitBoxToText', 'on', 'BackgroundColor', 'lightyellow');
    
    sgtitle('1996国赛B题:节水洗衣机优化结果', 'FontSize', 14, 'FontWeight', 'bold');
end

代码解析:

  1. subplot(1,3,k) 布局: 三张图并排,第一张展示优化目标随轮次的变化趋势,第二张展示最优方案的物理过程,第三张直观对比节水效果。这三张图形成了一个完整的"结果叙事"。

  2. yline 的使用: 用水平参考线标注理论极限和传统洗衣机基准,是数据可视化中的好习惯——让读者一眼看清当前结果与关键基准的关系。

  3. 颜色设计: 可行方案用蓝色,最优点用红星,传统方案用红色虚线,节水方案用绿色——颜色传递信息(绿色=好,红色=警告/对比基准)。

  4. 竞赛建议: 在论文中,不要直接截图MATLAB图形,而应该用AI或专业软件重绘,或者在MATLAB中设置好字体大小(至少12pt)、线条粗细和颜色方案,确保图形清晰可读。

13.5 灵敏度分析函数

%% sensitivity_analysis.m
% 功能:分析模型对关键参数的灵敏度
% 分析参数:衣物吸水量w、残留率阈值epsilon

function sensitivity_analysis(params_base)

    fprintf('\n=== 灵敏度分析 ===\n');
    
    figure('Name', '灵敏度分析', 'NumberTitle', 'off', 'Position', [100, 100, 1000, 400]);
    
    %% 分析1:吸水量w的影响
    subplot(1, 2, 1);
    
    w_range = 5:2:25;           % w从5升到25升
    V_opt_w = zeros(size(w_range));
    n_opt_w = zeros(size(w_range));
    
    for i = 1:length(w_range)
        params_temp = params_base;
        params_temp.w = w_range(i);
        
        % 重新优化(简化版,直接枚举)
        V_min = inf;
        n_best = 1;
        for n = 1:params_temp.n_max
            v_needed = params_temp.w * (params_temp.epsilon^(-1/n) - 1);
            if v_needed >= params_temp.v_min && v_needed <= params_temp.V_max
                V_total = n * v_needed;
                if V_total < V_min
                    V_min = V_total;
                    n_best = n;
                end
            end
        end
        V_opt_w(i) = V_min;
        n_opt_w(i) = n_best;
    end
    
    yyaxis left;
    plot(w_range, V_opt_w, 'b-o', 'LineWidth', 2, 'MarkerFaceColor', 'b');
    ylabel('最优总用水量 V* (升)', 'Color', 'b');
    
    yyaxis right;
    plot(w_range, n_opt_w, 'r-s', 'LineWidth', 2, 'MarkerFaceColor', 'r');
    ylabel('最优轮次 n*', 'Color', 'r');
    
    xlabel('衣物吸水量 w (升)');
    title('吸水量w对最优方案的影响');
    grid on;
    
    %% 分析2:残留率阈值epsilon的影响
    subplot(1, 2, 2);
    
    eps_range = [0.005, 0.01, 0.02, 0.03, 0.05, 0.08, 0.1];
    V_opt_eps = zeros(size(eps_range));
    n_opt_eps = zeros(size(eps_range));
    
    for i = 1:length(eps_range)
        params_temp = params_base;
        params_temp.epsilon = eps_range(i);
        
        V_min = inf;
        n_best = 1;
        for n = 1:params_temp.n_max
            v_needed = params_temp.w * (params_temp.epsilon^(-1/n) - 1);
            if v_needed >= params_temp.v_min && v_needed <= params_temp.V_max
                V_total = n * v_needed;
                if V_total < V_min
                    V_min = V_total;
                    n_best = n;
                end
            end
        end
        V_opt_eps(i) = V_min;
        n_opt_eps(i) = n_best;
    end
    
    yyaxis left;
    semilogx(eps_range*100, V_opt_eps, 'b-o', 'LineWidth', 2, 'MarkerFaceColor', 'b');
    ylabel('最优总用水量 V* (升)', 'Color', 'b');
    
    yyaxis right;
    semilogx(eps_range*100, n_opt_eps, 'r-s', 'LineWidth', 2, 'MarkerFaceColor', 'r');
    ylabel('最优轮次 n*', 'Color', 'r');
    
    xlabel('允许残留率 ε (%)');
    title('残留率阈值ε对最优方案的影响');
    grid on;
    
    sgtitle('灵敏度分析:关键参数对最优方案的影响', 'FontSize', 13, 'FontWeight', 'bold');
    
    % 打印灵敏度结论
    fprintf('w变化范围: %.0f~%.0f升,对应V*变化范围: %.1f~%.1f升\n', ...
            min(w_range), max(w_range), min(V_opt_w), max(V_opt_w));
    fprintf('epsilon变化范围: %.1f%%~%.1f%%,对应V*变化范围: %.1f~%.1f升\n', ...
            min(eps_range)*100, max(eps_range)*100, min(V_opt_eps), max(V_opt_eps));
end

代码解析:

  1. 双 Y 轴(yyaxis)的使用: 因为 V ∗ V^* V n ∗ n^* n 的量纲不同(一个是升,一个是无量纲整数),用双 Y 轴在同一图中展示更直观。

  2. semilogx(半对数坐标)的使用: 残留率阈值 ϵ \epsilon ϵ 的变化范围跨越一个数量级(0.5%到10%),用对数坐标可以更清晰地展示小数值区域的变化。

  3. 灵敏度分析的目的: 告诉评委和读者——我们的模型不是"碰巧"在特定参数下有好结果,而是在合理参数范围内普遍有效。这大大增强了结论的可信度。

十四、结果展示与分析

14.1 主要结果(模拟结果示例)

⚠️ 说明:以下结果为基于假设参数( w = 10 w=10 w=10升, ϵ = 2 \epsilon=2% ϵ=2)的模拟计算结果,不是真实实验数据。

最优方案:

指标 传统洗衣机 节水洗衣机(优化方案)
漂洗轮次 3轮 8~10轮
每轮用水量 40升 6~8升
总用水量 120升 约58~61升
最终残留率 0.08% ≤2%(满足标准)
节水率 约49~52%

14.2 结果如何对应题目要求

题目要求"总量最少":✅ 我们找到了给定参数下的全局最优解。

题目要求"满足洗涤效果":✅ 残留率恰好满足 ϵ = 2 \epsilon=2% ϵ=2 约束(取等号,即刚好满足,不浪费)。

题目要求"对比传统洗衣机":✅ 节水率约50%,有显著节水效果。

14.3 结果的现实意义

  1. 节水约50%:每次洗衣可节省约60升水,以一个四口之家每周洗衣3次计算,每年可节约约9000升水,相当于一个中等家庭一个月的生活用水量。

  2. 轮次增加但更节水:直觉上,“多轮"意味着"更耗水”——但模型证明恰恰相反。每轮少量用水、多轮漂洗的策略,总用水量显著低于传统的每轮大量用水。这是反直觉的结论,也是这道题最有价值的建模发现。

  3. 理论极限的意义 lim ⁡ V ∗ = − w ln ⁡ ϵ \lim V^* = -w\ln\epsilon limV=wlnϵ 告诉我们节水的"物理边界"在哪里,帮助工程师评估技术可行性。

14.4 异常现象说明

  • 为什么轮次越多总水量越少,但趋于平缓? 因为 V ∗ ( n ) = n w ( ϵ − 1 / n − 1 ) V^*(n) = nw(\epsilon^{-1/n}-1) V(n)=nw(ϵ1/n1) 是关于 n n n 的单调递减函数,但递减速率越来越慢,渐近于理论极限。实际工程中,超过8~10轮后收益递减,不值得进一步增加。

  • 为什么节水洗衣机的残留率(2%)反而高于传统洗衣机(0.08%)? 因为传统洗衣机"浪费"了大量水来实现远超标准的清洁度。节水洗衣机恰好达标,不多也不少——这才是真正的"优化"。很多初学者误以为"残留率越低越好",但这道题明确要求的是"在满足标准的前提下用水最少",不是"用最多水把衣服洗最干净"。

十五、模型检验

15.1 误差分析

本题为纯机理模型,主要误差来源于模型假设与现实的偏差:

误差来源 影响方向 量级估计
吸水量 w w w 的估计误差 直接影响最优 v ∗ v^* v w w w 估计偏大10%, V ∗ V^* V 偏大约8%
混合均匀假设违反 模型偏乐观 实际残留率可能高于预测值5%~15%
洗涤剂吸附效应忽略 模型偏乐观 需要实验数据校正
脱水效率变化忽略 随机误差 通常影响较小( < 5 <5% <5

误差控制建议:

  • w w w 进行保守估计(偏大),确保模型结果偏安全;
  • 将标准阈值从2%收紧到1.5%,为混合不均匀留出安全余量。

15.2 灵敏度分析结论

从灵敏度分析结果(模拟)中观察:

对吸水量 w w w 的灵敏度:

  • w w w 从5升增加到25升时, V ∗ V^* V 相应地从约29升增加到约145升,近似线性关系。
  • 这说明 w w w 是最关键参数,工程实践中应当准确测定。

对残留率阈值 ϵ \epsilon ϵ 的灵敏度:

  • ϵ \epsilon ϵ 从0.5%放宽到10%时, V ∗ V^* V 从约80升降至约35升。
  • 这给出了一个重要的政策建议:在保证卫生安全的前提下,合理放宽洗涤标准,可以显著降低用水量。

15.3 稳定性分析

对最优方案进行小扰动测试:在 v ∗ v^* v 基础上±10%扰动每轮用水量,观察残留率变化:

r n ′ = ∏ k = 1 n w w + v ∗ ( 1 + δ k ) r_n' = \prod_{k=1}^{n} \frac{w}{w + v^*(1+\delta_k)} rn=k=1nw+v(1+δk)w

δ k ∈ [ − 0.1 , 0.1 ] \delta_k \in [-0.1, 0.1] δk[0.1,0.1] 时,残留率变化约在 [ − 15 [-15%, +20%] [15 范围内。说明:

  • 向正扰动(多用水):残留率降低,洗涤效果更好;
  • 向负扰动(少用水):残留率升高,可能违反约束。

因此,实际控制系统应预留10%~20%的余量,即每轮实际用水量设为 1.1 v ∗ 1.1v^* 1.1v~ 1.2 v ∗ 1.2v^* 1.2v

15.4 鲁棒性分析

%% 鲁棒性分析代码片段(包含在sensitivity_analysis.m中)

% Monte Carlo 分析:参数同时扰动下的最优方案稳定性
N_sim = 1000;
V_sim = zeros(N_sim, 1);

for i = 1:N_sim
    params_mc = params_base;
    % 对w进行±20%随机扰动
    params_mc.w = params_base.w * (1 + 0.2*(2*rand()-1));
    
    % 求最优解
    V_min = inf;
    for n = 1:params_mc.n_max
        v_n = params_mc.w * (params_mc.epsilon^(-1/n) - 1);
        if v_n >= params_mc.v_min && v_n <= params_mc.V_max
            V_total = n * v_n;
            if V_total < V_min
                V_min = V_total;
            end
        end
    end
    V_sim(i) = V_min;
end

fprintf('Monte Carlo鲁棒性分析(N=%d次):\n', N_sim);
fprintf('  最优总水量均值: %.2f升\n', mean(V_sim));
fprintf('  标准差: %.2f升\n', std(V_sim));
fprintf('  95%%置信区间: [%.2f, %.2f]升\n', quantile(V_sim, 0.025), quantile(V_sim, 0.975));

十六、模型优缺点

16.1 模型优点

优点一:物理机制清晰。 递推方程直接来自质量守恒和稀释原理,不依赖黑箱方法,结果具有物理可解释性。

优点二:解析解优雅。 通过均值不等式证明了等量分水的最优性,将高维优化问题降为一维枚举,计算效率极高。

优点三:给出了理论极限。 lim ⁡ V ∗ = − w ln ⁡ ϵ \lim V^* = -w\ln\epsilon limV=wlnϵ 这个解析结果告诉工程师"节水潜力的物理上界",对产品设计有直接指导意义。

优点四:对比分析完整。 模型不仅给出节水方案,还与传统洗衣机进行定量对比,结论具有实用价值。

16.2 模型缺点与改进方向

缺点一:均匀混合假设过强。 实际漂洗中,洗涤剂在衣物纤维中的分布是不均匀的,简单稀释模型高估了漂洗效率。

改进方向: 引入"有效混合率" η ∈ ( 0 , 1 ) \eta \in (0,1) η(0,1),将递推方程修改为:

m k = m k − 1 ⋅ w w + η v k m_k = m_{k-1} \cdot \frac{w}{w + \eta v_k} mk=mk1w+ηvkw

缺点二:忽略了洗涤剂在纤维中的物理吸附。 有些洗涤剂分子会被纤维吸附,不能被简单冲洗去除。

改进方向: 引入吸附动力学模型(如Langmuir等温线),建立更真实的多相传质模型。

缺点三:单一目标优化。 只考虑节水,没有考虑时间成本(轮次多则时间长)和电能消耗。

改进方向: 构建多目标优化模型:

min ⁡ V t o t a l , T t o t a l , E t o t a l \min {V_{total}, T_{total}, E_{total}} minVtotal,Ttotal,Etotal

使用Pareto前沿分析,为消费者提供可选择的"偏好方案"(如偏好省水型、偏好省时型)。

缺点四:参数假设未经实验验证。 w w w ϵ \epsilon ϵ 等参数来自估计,结论的精度依赖于参数精度。

改进方向: 建议开展实测实验,用实测数据校准 w w w 参数,并用留一法交叉验证模型预测精度。

十七、论文写作建议

17.1 摘要写法

摘要是论文的"门面",评委通常先看摘要决定是否仔细阅读。数学建模竞赛摘要需要在300~500字内回答以下问题:

  1. 这道题是什么类型的问题?
  2. 针对每个子问题,你建立了什么模型?
  3. 用什么方法求解?
  4. 得到了什么关键结论?
  5. 这个结论有什么实际意义?

摘要写法误区: 很多同学把摘要写成"本文研究了节水洗衣机问题,建立了数学模型,经过计算得出了结论"——这等于什么都没说。摘要必须有具体数字和具体结论。

17.2 关键词选择

好的关键词应覆盖:问题类型 + 模型名称 + 核心方法

例如:节水优化差分递推模型均值不等式参数灵敏度分析多轮漂洗策略

17.3 问题重述写法

问题重述≠题目复述。题目复述是把题目原文抄一遍,而问题重述是用自己的数学语言重新描述问题

好的问题重述应包含:

  • 已知什么(量化表达);
  • 求什么(用数学符号);
  • 约束是什么。

17.4 模型假设写法

每条假设必须包含:

  • 假设内容(是什么);
  • 为什么需要(为什么);
  • 违反后的影响(局限性)。

不要写"假设洗涤效果良好"这样的废话假设。

17.5 符号说明写法

符号表要完整、统一,且与正文完全一致。建议使用LaTeX格式,表格对齐,每个符号都有量纲。

17.6 模型建立写法

不要一上来就列公式。写模型建立时,应该先用自然语言描述建模思路,再引出公式,公式后紧跟参数解释。

17.7 结果分析写法

结果分析不是"结果表格 + 一句’结果合理’"。应包含:数值说明、现实解释、图表指向、异常讨论、结论提炼。

17.8 参考文献写法

注意:参考文献要真实存在,不要凭空捏造。建议引用:

  • 相关教材(运筹学、数学建模教材);
  • 洗涤化学领域的综述文章;
  • 已发表的相关建模论文。

17.9 附录代码整理方式

附录中的代码应:

  • 按模块分类整理,不要一整段;
  • 保留中文注释;
  • 标注运行环境(MATLAB版本);
  • 说明如何运行(运行哪个文件,输入什么参数)。

十八、数学建模论文摘要示例

以下是符合数学建模竞赛风格的中文摘要示例,供参考。

摘要

本文针对1996年全国大学生数学建模竞赛B题"节水洗衣机",建立了基于浓度递推原理的洗涤过程数学模型,并通过解析推导与数值优化,给出了满足洗涤效果约束下总用水量最小的最优控制策略。

针对问题一,基于质量守恒定律和均匀混合假设,建立了洗涤剂残留量的差分递推方程: m k = m k − 1 ⋅ w / ( w + v k ) m_k = m_{k-1} \cdot w/(w+v_k) mk=mk1w/(w+vk),并推导出 n n n 轮后残留率的乘积公式 r n = ∏ k = 1 n w / ( w + v k ) r_n = \prod_{k=1}^{n} w/(w+v_k) rn=k=1nw/(w+vk)。该公式揭示了漂洗效果与各轮加水量的定量关系。

针对问题二,利用算术-几何均值不等式,严格证明了在总用水量 V V V 和轮次 n n n 固定的条件下,各轮平均分配用水量( v i = V / n v_i = V/n vi=V/n)是使最终残留率最低的最优策略,同时使残留率达到解析最小值 r n ∗ = [ w / ( w + V / n ) ] n r_n^* = [w/(w+V/n)]^n rn=[w/(w+V/n)]n

针对问题三,基于等量分水最优结论,建立了最优轮次与最优用水量的联合优化模型。通过对轮次 n n n 的整数枚举,解析给出每一轮次下满足约束的最小用水量 v ∗ ( n ) = w ( ϵ − 1 / n − 1 ) v^*(n) = w(\epsilon^{-1/n}-1) v(n)=w(ϵ1/n1),进而确定全局最优方案。当衣物吸水量 w = 10 w=10 w=10 升、残留率标准 ϵ = 2 \epsilon=2% ϵ=2 时,最优方案为漂洗 8~10轮、每轮用水约 6~8升,总用水量约 58~61升,较传统洗衣机(3轮×40升=120升)节水约 49%~52%。同时推导出最优总用水量的理论下界 V m i n = − w ln ⁡ ϵ ≈ 39.1 V_{min} = -w\ln\epsilon \approx 39.1 Vmin=wlnϵ39.1 升。

模型的灵敏度分析表明,结果对吸水量参数 w w w 较为敏感,建议在工程实现中预留10%~20%的水量余量。模型假设的主要局限性在于均匀混合假设,实际工程中可通过引入有效混合率加以修正。

关键词:节水优化;洗涤剂浓度递推;均值不等式;最优轮次;参数灵敏度分析

十九、常见问题与踩坑总结

Q1:拿到数学建模题目后为什么不能马上写代码?

这是最经典的误区。拿到题目立刻打开MATLAB的同学,通常会在写了一半代码后发现:我不知道这个函数的输出是什么,我不知道这个变量的物理意义,我不知道约束条件是什么。

正确的顺序是:读题→理解物理机制→定义变量→建立数学模型→确定求解方法→写代码。代码是数学模型的翻译,必须先有模型才能写代码。从题目到代码,中间有三层(问题理解→数学建模→算法设计),每一层都不能跳过。

Q2:问题重述和题目复述有什么区别?

题目复述是"把原题抄一遍",而问题重述是"用数学语言重新描述问题"。

以本题为例:

  • 复述:“请为洗衣机设计一种程序,使得在满足一定洗涤效果的条件下,总量最少。”
  • 重述:“设第 k k k 轮加水量为 v k v_k vk,衣物吸附水量为 w w w,洗涤效果标准为 r n ≤ ϵ r_n \leq \epsilon rnϵ,求最优决策 ( n ∗ , v 1 ∗ , … , v n ∗ ∗ ) (n^*, v_1^*, \ldots, v_{n^*}^*) (n,v1,,vn) 使 ∑ v k \sum v_k vk 最小。”

重述的核心是数学化,不是长度。

Q3:模型假设是不是越多越好?

不是。假设的数量不重要,质量才重要。每条假设都应该是建立后续模型所必需的,而不是为了凑数。

错误示范:假设1:洗衣机正常运行。假设2:衣物是干净的。(这些假设对建模毫无帮助)

正确做法:只写那些"如果去掉这条假设,模型就无法建立或需要大幅修改"的假设。

Q4:为什么公式很多但论文依然得分不高?

公式多不等于模型好。评委看的是:

  1. 公式从何而来(推导过程);
  2. 公式变量是什么(定义清晰);
  3. 公式说明了什么(含义解释);
  4. 公式如何求解(算法说明);
  5. 结果如何解读(分析讨论)。

"公式堆砌"是数学建模论文中的大忌。一个推导严谨、解释清晰的模型,远比一堆晦涩无解释的公式有价值。

Q5:MATLAB代码结果如何对应论文表格?

代码结果→论文表格需要一一对应,且表格标题应该说明数据来源和计算条件。

实践建议:在代码中使用 fprintfwritetable 直接输出格式化表格,复制到论文时只需调整格式。同时在论文中注明"表X由MATLAB计算得出,参数设置见附录A"。

Q6:没有附件数据时如何构建合理分析框架?

没有数据时,应该:

  1. 从物理/工程第一性原理推导模型;
  2. 查阅文献获取参数的合理范围;
  3. 用参数范围内的典型值计算结果;
  4. 通过灵敏度分析展示结果对参数的依赖性。

最忌讳的是"拍脑袋"给出参数然后假装数据是真实的——评委能看出来。

Q7:预测模型如何选择误差指标?

选择误差指标要根据数据特性:

  • 如果数据中有极端值(异常值),用MAE(对异常值不敏感);
  • 如果需要惩罚大误差,用RMSE(对大误差更敏感);
  • 如果需要反映相对误差,用MAPE(百分比形式,便于解释);
  • 如果需要综合评价拟合优度,用

不要在同一论文中只用一种指标,建议报告至少2~3种。

Q8:评价模型中权重如何确定?

权重确定是评价模型的核心,主要方法有:

  1. 主观法:德尔菲法、层次分析法(AHP);
  2. 客观法:熵权法、CRITIC法、主成分分析;
  3. 组合法:将主观权重和客观权重加权平均。

选择哪种方法要根据题目情境:有专家意见时用主观法,只有数据时用客观法,两者都有时用组合法。无论哪种方法,都要在论文中说明权重的合理性,不能"拍脑袋给权重"。

Q9:优化模型如何确定目标函数和约束条件?

目标函数来自题目中"最大/最小化什么",约束条件来自题目中"满足什么条件"。

提炼方法:“从题目中找所有量→分类为决策变量、约束参数和目标→建立关系”。

常见误区:把约束条件混入目标函数,或把目标函数变成约束条件。本题中"用水量最小"是目标,"残留率≤ε"是约束,不能反过来。

Q10:国赛论文和美赛论文写法有什么区别?

维度 国赛 美赛
语言 中文 英文
结构 较固定(必须有摘要、假设、符号等标准章节) 相对灵活,但需有Summary Sheet
摘要 约300~500字,位于首页 约400~600字,作为独立Summary Sheet
图表 规范即可 要求较高,应有标题、来源标注
代码 通常放附录 通常放附录,有时要求链接或说明
风格 严谨学术 更注重创新性和"讲故事"能力

Q11:如何避免论文像代码说明书?

“代码说明书"型论文的特征:每段都是"这段代码定义了变量X,然后计算了Y,输出了Z”。

避免的方法:写论文时,以数学模型为主线,代码只是实现工具,放附录。正文中说的是"建立了什么模型,用什么方法求解,得到了什么结论",不是"写了什么代码"。

Q12:如何写出高质量摘要?

参照"SCR结构":Situation(背景)→Challenge(问题)→Resolution(解决方案)→Result(结论)。

每个部分控制在12句,整体300500字,包含具体数字和具体结论。

Q13:如何自然地提出模型改进?

改进建议要从"模型的局限性"出发,而不是凭空提出。先分析"这个假设在什么情况下会失效",再提出"如何修正"。

例如:本题中,均匀混合假设在快速漂洗时会失效,改进方向是引入"混合效率参数 η \eta η",并通过实验校定。这比说"可以用更好的算法"要具体得多。

Q14:模型优缺点如何写得具体?

优缺点不能只写"计算简单"、"假设合理"这种废话。应该写:

  • 优点:因为XX原因,这个模型在YY情况下比ZZ方法好/快/准;
  • 缺点:因为AA假设,当BB条件不满足时,模型误差会达到CC量级。

要有对比对象,要有量化说明。

Q15:附录代码应该如何整理?

  1. 按功能模块分段,每段有标题注释;
  2. 删去调试用的临时代码;
  3. 保留数据读取、核心计算、结果输出三个主要部分;
  4. 说明运行方法(运行哪个文件,期望输出什么);
  5. 如有多个函数文件,说明调用关系。

二十、总结

回顾整篇解析,我们从1996年这道看似简单的洗衣机题中,挖掘出了一套完整的建模思路:

核心建模发现:

  1. 物理机制决定模型结构:洗涤过程是离散稀释过程,自然导出差分递推方程,这是整个模型的基石。

  2. 数学工具化简优化维度:均值不等式的应用将 n n n 维分配问题化简为一维枚举,这是数学工具改变问题难度的典型案例。

  3. 解析解提供深刻洞见 V m i n = − w ln ⁡ ϵ V_{min} = -w\ln\epsilon Vmin=wlnϵ 这个优美的极限公式,不仅是计算结果,更是设计洗衣机时评估技术潜力的理论工具。

  4. 反直觉结论最有价值:“多轮少量"优于"少轮多量”——这个反直觉的结论,正是这道题最核心的建模价值所在。

给备赛同学的几句话:

数学建模竞赛考察的不是你会多少数学方法,而是你能不能用数学方法解决实际问题。建模能力的核心是从现实到数学的翻译能力——能把物理过程写成方程,能把工程约束写成不等式,能把优化目标写成函数。

这道题的物理过程(稀释)、数学工具(均值不等式)、求解策略(枚举+解析),都是可以迁移到其他问题的通用能力。希望你读完这篇文章,不仅学会了这道题,更建立起了一套可复用的建模思维框架。

加油,你比自己想象的更有潜力!


声明:以上内容部分基于人工智能辅助生成,仅供参考交流,不构成任何专业建议。模型输出可能存在偏差,使用前请自行核实,后果自负。欢迎理性讨论。

若需原题 PDF、附件或历年高教社杯真题,关注技术号 「猿圈奇妙屋」,回复【高教社杯】即可获取。

🎁 文末福利

本专栏内容源自实际建模经验、竞赛题目及读者需求。如涉及版权问题,请告知,将立即处理。部分解法思路参考了网络优秀文章,若未能完全契合你的场景,欢迎在评论区分享更优解法,共同探讨、共同进步!

更多建模方法、工具与竞赛题解,欢迎访问专栏 👉 《《滚雪球学数学建模(含历年真题)》

如果本文对你有帮助,欢迎点赞、收藏、关注,你的支持是我持续创作的动力!

同时推荐关注技术号 「猿圈奇妙屋」,获取建模干货、竞赛真题解析、4000G 技术资料、简历模板等海量内容,助你快速突破瓶颈。

🫵 关于作者

我是 bug菌,数学建模竞赛指导教师,曾指导学生斩获国赛一等奖、美赛 M 奖等,擅长运动学建模、优化模型、评价模型等方向。

活跃于 CSDN · 掘金 · InfoQ · 51CTO · 华为云 · 阿里云 · 腾讯云 · 开源中国 · 博客园 · 墨天轮 等平台

🏅 CSDN 博客之星 Top30 · 华为云十佳博主 · 掘金人气作者 Top40 · 多平台签约优质作者 · 全网粉丝 30w+

更多优质内容与成长资料 👉 点击查看 👈

欢迎加入硬核技术号 「猿圈奇妙屋」,一起进阶打怪!

- End -

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐