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

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

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

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

全文目录:

1999B题:钻井布局

真题展示

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

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

很多同学第一次看到这道题,会觉得"不就是个距离判断嘛,写个循环就行了"。但实际上,这道题是一道极具迷惑性的几何优化题——表面上是判断旧井能否被利用,背后隐藏的是一个连续优化问题:网格怎么移动、怎么旋转,才能让尽可能多的旧井落入网格节点的误差范围内?

这类题目的建模难点在于:

  1. 目标函数不连续:判断"旧井能否被利用"本质上是一个整数(0或1),但网格的平移量是连续变量,导致目标函数出现跳跃性,不能直接用梯度法求解。
  2. 问题二引入旋转自由度:一旦网格可以旋转,搜索空间从二维变成三维( Δ x , Δ y , θ \Delta x, \Delta y, \theta Δx,Δy,θ),问题复杂度大幅上升。
  3. 问题三要求全部利用:从"最多利用多少"变成"能否全部利用",是从优化问题变成可行性判断问题,思路需要根本性转变。

我带过不少建模队伍,这道题最常见的错误有两类:

  • 第一类:只考虑网格平移,忽略了网格是"整体刚性移动"的,不能单独调整每个节点。
  • 第类:把问题三理解成"优化问题",实际上它是一个判断问题,需要给出充分必要条件。

接下来,我们系统地把这道题拆开来讲。

二、题目背景与现实意义

背景解读

勘探部门在某地区寻找矿藏。初步勘探阶段已打了若干旧井,获取了地质资料。进入系统勘探阶段后,需要在一个正方形网格的所有节点处布置新井(称为"撒网式"勘探)。

核心经济逻辑:打一口新井需要500万元,利用一口旧井资料只需10万元,节省490万元。如果旧井恰好(或接近)落在某个网格节点上,就不需要在该节点重新钻井。

关键约束:只要旧井位置距离某网格节点不超过误差 ε = 0.05 \varepsilon = 0.05 ε=0.05(单位),就认为该旧井资料可以代替该节点处的新井。

现实意义

这道题反映了实际工程中的资源复用优化问题:

  • 在石油、矿产勘探中,如何在保证勘探精度的前提下,最大化利用已有资料,减少重复投入;
  • 类似问题广泛存在于:无线基站布局优化、传感器网络部署、遥感卫星地面站选址等领域;
  • 核心思想是:用连续优化的方式,解决离散资源匹配问题

三、题目重述

3.1 已知条件

  1. 平面上有 n n n 个已有井位(旧井),坐标为 P i = ( a i , b i ) P_i = (a_i, b_i) Pi=(ai,bi) i = 1 , 2 , ⋯   , n i = 1, 2, \cdots, n i=1,2,,n
  2. 新布置的井位是一个正方形网格 N N N 的所有节点,网格每个格子边长为1单位(约100米);
  3. 网格可以在平面上任意平移(问题一),也可以任意平移+旋转(问题二);
  4. 误差阈值 ε = 0.05 \varepsilon = 0.05 ε=0.05 单位;
  5. 若旧井 P i P_i Pi 距某网格节点 X j X_j Xj 的距离不超过 ε \varepsilon ε,则认为该旧井资料可利用,不必在 X j X_j Xj 处打新井;
  6. 给出数值算例: n = 12 n=12 n=12,坐标如下表所示。
i i i 1 2 3 4 5 6 7 8 9 10 11 12
a i a_i ai 0.50 1.41 3.00 3.37 3.40 4.72 4.72 5.43 7.57 8.38 8.98 9.50
b i b_i bi 2.00 3.50 1.50 3.51 5.50 2.00 6.24 4.10 2.01 4.50 3.41 0.80

3.2 待解决问题

问题一:网格横向和纵向固定(不旋转),距离定义为切比雪夫距离(横坐标差绝对值与纵坐标差绝对值的最大值)。求网格如何平移,使可利用的旧井数尽可能多。给出数值计算方法,并对数值算例计算。

问题二:在欧氏距离意义下,考虑网格可旋转的情形,给出算法及计算结果。

问题三:给出判定 n n n 口旧井均可被利用的条件和算法(距离类型可自选)。

3.3 附件数据说明

题目直接在正文中给出了 n = 12 n=12 n=12 的数值算例(见上表),无需读取外部附件。以下代码将直接使用这组数据。

四、问题分析

4.1 问题一分析

问题本质:切比雪夫距离下,网格平移的连续优化问题。

切比雪夫距离定义为:
d ∞ ( P i , X j ) = max ⁡ ( ∣ a i − x j ∣ , ∣ b i − y j ∣ ) d_{\infty}(P_i, X_j) = \max(|a_i - x_j|, |b_i - y_j|) d(Pi,Xj)=max(aixj,biyj)

其中 ( x j , y j ) (x_j, y_j) (xj,yj) 是网格节点坐标。

关键观察:网格节点坐标可以表示为:
X j = ( m + t x , , k + t y ) , m , k ∈ Z X_j = (m + t_x, , k + t_y), \quad m, k \in \mathbb{Z} Xj=(m+tx,,k+ty),m,kZ

其中 ( t x , t y ) (t_x, t_y) (tx,ty) 是网格的平移量,且 t x , t y ∈ [ 0 , 1 ) t_x, t_y \in [0, 1) tx,ty[0,1)(超出一个周期就等价于回到原位)。

因此,判断旧井 P i = ( a i , b i ) P_i = (a_i, b_i) Pi=(ai,bi) 是否可被利用,等价于判断:
min ⁡ m , k ∈ Z d ∞ ( ( a i , b i ) , ( m + t x , k + t y ) ) ≤ ε \min_{m,k \in \mathbb{Z}} d_{\infty}((a_i, b_i), (m+t_x, k+t_y)) \leq \varepsilon m,kZmind((ai,bi),(m+tx,k+ty))ε

这等价于:
min ⁡ ( a i − t x 1 , b i − t y 1 ) ≤ ε \min\left({a_i - t_x}_1, {b_i - t_y}_1\right) \leq \varepsilon min(aitx1,bity1)ε

其中 x 1 = min ⁡ ( x   m o d   1 , , 1 − x   m o d   1 ) {x}_1 = \min(x \bmod 1, , 1 - x \bmod 1) x1=min(xmod1,,1xmod1) 表示 x x x 到最近整数的距离。

变量空间降维:搜索空间从无穷多个网格节点,压缩为二维参数 ( t x , t y ) ∈ [ 0 , 1 ) 2 (t_x, t_y) \in [0,1)^2 (tx,ty)[0,1)2

建模经验:这道题的关键简化步骤就在这里。很多同学想枚举"哪个节点离哪口井最近",这样做复杂度极高,而且没有抓住网格的周期性特征。认识到"只需搜索一个周期内的平移量",是解题的核心突破口。

4.2 问题二分析

问题本质:欧氏距离下,网格平移+旋转的三维优化问题。

当网格可以旋转角度 θ \theta θ 时,网格节点坐标变为:
X m , k ( θ , t x , t y ) = ( cos ⁡ θ − sin ⁡ θ   sin ⁡ θ cos ⁡ θ ) ( m   k ) + ( t x   t y ) X_{m,k}(\theta, t_x, t_y) = \begin{pmatrix} \cos\theta & -\sin\theta \ \sin\theta & \cos\theta \end{pmatrix} \begin{pmatrix} m \ k \end{pmatrix} + \begin{pmatrix} t_x \ t_y \end{pmatrix} Xm,k(θ,tx,ty)=(cosθsinθ sinθcosθ)(m k)+(tx ty)

判断旧井 P i P_i Pi 是否可被利用,需要在旋转坐标系下做判断:
d 2 ( P i , X m , k ) = ( a i − X m , k x ) 2 + ( b i − X m , k y ) 2 ≤ ε d_2(P_i, X_{m,k}) = \sqrt{(a_i - X_{m,k}^x)^2 + (b_i - X_{m,k}^y)^2} \leq \varepsilon d2(Pi,Xm,k)=(aiXm,kx)2+(biXm,ky)2 ε

难点:搜索空间变成三维 ( θ , t x , t y ) (\theta, t_x, t_y) (θ,tx,ty),且目标函数不连续(阶跃型)。

处理策略

  1. 将旧井坐标反变换到旋转网格的局部坐标系;
  2. 在局部坐标系下,问题退化为问题一(欧氏距离下的平移优化);
  3. 遍历角度 θ ∈ [ 0 ° , 90 ° ) \theta \in [0°, 90°) θ[,90°)(利用正方形网格的对称性,只需搜索90°范围)。

4.3 问题三分析

问题本质:从"最优化"转变为"可行性判断"——什么条件下所有旧井同时可被利用?

这是三道题中建模难度最高的一问。需要回答:

给定 n n n 个点,是否存在一个网格(平移+旋转),使得每个点都距某节点不超过 ε \varepsilon ε

必要条件分析

  • 任意两口旧井之间的距离,必须满足一定的几何约束;
  • 若选用切比雪夫距离,则可转化为:所有旧井在 ( a i 1 , b i 1 ) ({a_i}_1, {b_i}_1) (ai1,bi1) 空间中的聚类问题。

4.4 各问题之间的逻辑关系

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

逻辑关系说明

  • 问题一是基础,建立了"周期性平移"的核心思想;
  • 问题二在问题一基础上引入旋转自由度,是问题一的扩展;
  • 问题三是对前两问的逻辑升华,从"求最优"变成"判断可行"。

五、整体建模思路

5.1 建模路线

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

流程说明:整个建模过程遵循"从简到繁、从特殊到一般"的原则。先处理不旋转的情形(问题一),掌握周期性搜索的核心技巧;再扩展到旋转(问题二);最后讨论全部利用的理论条件(问题三)。

5.2 模型选择依据

问题 模型类型 选择依据
问题一 离散参数网格搜索 目标函数不可微,梯度法失效;切比雪夫距离可分离,可独立处理横纵坐标
问题二 粗搜索+精细优化 三维搜索空间,先粗后精;旋转对称性压缩搜索范围
问题三 几何条件分析 + 聚类 从充要条件角度分析,转化为覆盖问题

5.3 算法实现思路

问题一核心算法(切比雪夫距离):

关键变换: r i x = a i − t x 1 , r i y = b i − t y 1 \text{关键变换:} \quad r_i^x = {a_i - t_x}_1, \quad r_i^y = {b_i - t_y}_1 关键变换:rix=aitx1,riy=bity1

其中 z 1 = min ⁡ ( z   m o d   1 , 1 − z   m o d   1 ) {z}_1 = \min(z \bmod 1, 1 - z \bmod 1) z1=min(zmod1,1zmod1),表示 z z z 到最近整数的距离。

则旧井 i i i 可被利用当且仅当:
max ⁡ ( r i x , r i y ) ≤ ε \max(r_i^x, r_i^y) \leq \varepsilon max(rix,riy)ε

目标:寻找 ( t x , t y ) (t_x, t_y) (tx,ty) 使满足上式的 i i i 的数量最多。

5.4 结果验证方法

  1. 可视化验证:在坐标系中画出最优网格和旧井位置,目视检查;
  2. 逐井验证:对每口旧井计算其到最近网格节点的距离,确认不超过 ε \varepsilon ε
  3. 扰动验证:对最优 ( t x , t y ) (t_x, t_y) (tx,ty) 施加小扰动,观察可利用井数是否稳定。

六、数据预处理

6.1 数据读取

题目数据直接给出,无需读取外部文件。

% data_preprocess.m
function [a, b, n, epsilon] = data_preprocess()
% 功能:读取并预处理钻井布局题目数据
% 输出:
%   a       - 旧井横坐标向量 (1×n)
%   b       - 旧井纵坐标向量 (1×n)
%   n       - 旧井数量
%   epsilon - 误差阈值

clc;
fprintf('===== 钻井布局数据预处理 =====\n');

% 题目给出的12口旧井坐标
a = [0.50, 1.41, 3.00, 3.37, 3.40, 4.72, 4.72, 5.43, 7.57, 8.38, 8.98, 9.50];
b = [2.00, 3.50, 1.50, 3.51, 5.50, 2.00, 6.24, 4.10, 2.01, 4.50, 3.41, 0.80];

n = length(a);       % 旧井数量
epsilon = 0.05;      % 误差阈值(题目给定)

% 打印基本统计信息
fprintf('旧井数量 n = %d\n', n);
fprintf('误差阈值 ε = %.2f\n', epsilon);
fprintf('横坐标范围:[%.2f, %.2f]\n', min(a), max(a));
fprintf('纵坐标范围:[%.2f, %.2f]\n', min(b), max(b));
fprintf('数据读取完成。\n\n');
end

代码解析

  • 这段代码将数据封装为函数,便于被主程序调用,也便于后续替换为真实数据;
  • 输出 epsilon=0.05 作为参数传递,方便后续灵敏度分析时修改;
  • 初学者注意:MATLAB中行向量用[]+逗号分隔,列向量用;分隔。

6.2 缺失值与异常值处理

本题数据由题目直接给出,精度合理,无缺失值。但在实际竞赛中,若数据来自附件,需进行如下检查:

% 检查是否有NaN或Inf
if any(isnan(a)) || any(isnan(b))
    warning('数据中存在缺失值,已自动剔除');
    valid = ~(isnan(a) | isnan(b));
    a = a(valid); b = b(valid);
end

% 检查坐标是否为负(本题中坐标应为正值)
if any(a < 0) || any(b < 0)
    warning('存在负坐标,请检查数据');
end

6.3 可视化分析

% plot_raw_data.m
function plot_raw_data(a, b, epsilon)
% 功能:可视化旧井分布

figure('Name', '旧井分布图', 'Position', [100, 100, 800, 600]);

% 绘制旧井位置
scatter(a, b, 80, 'r', 'filled', 'DisplayName', 'Old Wells');
hold on;

% 在每口井周围画误差圆(欧氏距离意义)
theta_circle = linspace(0, 2*pi, 100);
for i = 1:length(a)
    x_circle = a(i) + epsilon * cos(theta_circle);
    y_circle = b(i) + epsilon * sin(theta_circle);
    plot(x_circle, y_circle, 'b--', 'LineWidth', 0.5, 'HandleVisibility', 'off');
end

% 添加井编号标注
for i = 1:length(a)
    text(a(i)+0.1, b(i)+0.1, sprintf('P_%d', i), 'FontSize', 8, 'Color', 'k');
end

xlabel('X Coordinate (units)', 'FontSize', 12);
ylabel('Y Coordinate (units)', 'FontSize', 12);
title('Distribution of Existing Wells (n=12)', 'FontSize', 14);
legend('show', 'Location', 'best');
grid on; axis equal;
hold off;
end

代码解析

  • 每口井周围画的误差圆,直观展示了"旧井利用的容许范围";
  • axis equal 保证横纵比例一致,避免图形变形导致误判;
  • 这张图应该放入论文的"数据说明"章节,让读者直观理解问题规模。

七、模型假设

  1. 平面性假设:所有井位均在同一水平面内,忽略地形高度差,仅考虑二维坐标;
  2. 刚性网格假设:正方形网格在平移和旋转过程中保持形状不变,每个格子的边长始终为1个单位;
  3. 周期性假设:网格向任意方向延伸至足以覆盖所有旧井位置,不考虑网格边界效应;
  4. 误差独立性假设:每口旧井与网格节点的距离判断相互独立,旧井与多个节点的误差关系不影响彼此;
  5. 距离度量假设:问题一使用切比雪夫距离,问题二使用欧氏距离,问题三可自选(本文选欧氏距离);
  6. 整数网格假设:网格节点的整数坐标部分 ( m , k ) ∈ Z 2 (m, k) \in \mathbb{Z}^2 (m,k)Z2,平移量 ( t x , t y ) (t_x, t_y) (tx,ty) 是连续参数;
  7. 成本线性假设:可利用旧井越多,节省费用越多,费用与利用数量呈线性关系。

写作提示:假设不是越多越好——只写与建模关键步骤直接相关的假设,且每条假设最好说明"为什么合理"。堆砌无关假设反而显得论文不成熟。

八、符号说明

符号 含义 单位/取值范围
n n n 旧井总数 正整数,本题 n = 12 n=12 n=12
P i = ( a i , b i ) P_i = (a_i, b_i) Pi=(ai,bi) i i i 口旧井的坐标 单位(约100米)
ε \varepsilon ε 误差阈值 ε = 0.05 \varepsilon = 0.05 ε=0.05
( t x , t y ) (t_x, t_y) (tx,ty) 网格平移量 t x , t y ∈ [ 0 , 1 ) t_x, t_y \in [0, 1) tx,ty[0,1)
θ \theta θ 网格旋转角度 θ ∈ [ 0 ° , 90 ° ) \theta \in [0°, 90°) θ[,90°)
X m , k X_{m,k} Xm,k 网格中整数坐标为 ( m , k ) (m,k) (m,k) 的节点 ( m + t x , k + t y ) (m+t_x, k+t_y) (m+tx,k+ty)(未旋转时)
d ∞ ( P , X ) d_\infty(P, X) d(P,X) P P P X X X 的切比雪夫距离 max ⁡ ( ∣ Δ x ∣ , ∣ Δ y ∣ ) \max(\vert\Delta x\vert, \vert\Delta y\vert) max(∣Δx,∣Δy)
d 2 ( P , X ) d_2(P, X) d2(P,X) P P P X X X 的欧氏距离 ( Δ x ) 2 + ( Δ y ) 2 \sqrt{(\Delta x)^2 + (\Delta y)^2} (Δx)2+(Δy)2
z 1 {z}_1 z1 z z z 到最近整数的距离 min ⁡ ( z   m o d   1 , 1 − z   m o d   1 ) \min(z \bmod 1, 1 - z \bmod 1) min(zmod1,1zmod1)
u i ( θ ) u_i(\theta) ui(θ) 旧井 i i i 在旋转坐标系下的横坐标 实数
v i ( θ ) v_i(\theta) vi(θ) 旧井 i i i 在旋转坐标系下的纵坐标 实数
f ( t x , t y ) f(t_x, t_y) f(tx,ty) 可利用旧井数量(目标函数) 0 , 1 , ⋯   , n 0, 1, \cdots, n 0,1,,n
N ∗ N^* N 最优可利用旧井数 正整数

九、模型一:基础模型(切比雪夫距离,仅平移)

9.1 模型思想

核心思想:利用网格的周期性,将无限大的搜索空间压缩为 [ 0 , 1 ) 2 [0,1)^2 [0,1)2 的二维参数空间。

关键几何性质:对于一个网格节点 X m , k = ( m + t x , k + t y ) X_{m,k} = (m + t_x, k + t_y) Xm,k=(m+tx,k+ty),旧井 P i = ( a i , b i ) P_i = (a_i, b_i) Pi=(ai,bi) 与"最近网格节点"的切比雪夫距离为:

d ∞ ( P i , nearest node ) = max ⁡ ( a i − t x 1 , b i − t y 1 ) d_\infty(P_i, \text{nearest node}) = \max\left({a_i - t_x}_1, {b_i - t_y}_1\right) d(Pi,nearest node)=max(aitx1,bity1)

其中:
z 1 = min ⁡ ( z   m o d   1 , ; 1 − z   m o d   1 ) {z}_1 = \min(z \bmod 1, ; 1 - z \bmod 1) z1=min(zmod1,;1zmod1)

物理含义 z 1 {z}_1 z1 z z z 到最近整数的距离,也就是"这口井在网格单元中距离最近边界的距离"。当 z z z 接近整数(接近网格线)时, z 1 {z}_1 z1 接近0,说明容易被某节点覆盖。

9.2 数学表达式

目标函数
max ⁡ t x , t y ∈ [ 0 , 1 ) f ( t x , t y ) = ∑ i = 1 n 1 [ max ⁡ ( a i − t x 1 , b i − t y 1 ) ≤ ε ] \max_{t_x, t_y \in [0,1)} f(t_x, t_y) = \sum_{i=1}^{n} \mathbb{1}\left[\max\left({a_i - t_x}_1, {b_i - t_y}_1\right) \leq \varepsilon\right] tx,ty[0,1)maxf(tx,ty)=i=1n1[max(aitx1,bity1)ε]

其中 1 [ ⋅ ] \mathbb{1}[\cdot] 1[] 为示性函数(条件成立取1,否则取0)。

等价改写:对每口井 i i i,定义其"容许平移区间"为:

横向: t x ∈ ⋃ m ∈ Z [ a i − m − ε , ; a i − m + ε ] ∩ [ 0 , 1 ) t_x \in \bigcup_{m \in \mathbb{Z}} [a_i - m - \varepsilon, ; a_i - m + \varepsilon] \cap [0,1) txmZ[aimε,;aim+ε][0,1)

纵向: t y ∈ ⋃ k ∈ Z [ b i − k − ε , ; b i − k + ε ] ∩ [ 0 , 1 ) t_y \in \bigcup_{k \in \mathbb{Z}} [b_i - k - \varepsilon, ; b_i - k + \varepsilon] \cap [0,1) tykZ[bikε,;bik+ε][0,1)

问题等价为:寻找 ( t x , t y ) (t_x, t_y) (tx,ty),使其同时落在尽可能多的井的"容许区间对"之内。

9.3 参数解释

  • t x , t y t_x, t_y tx,ty:这是模型的两个决策变量,代表网格相对于某固定参考系的平移量;
  • a i − t x 1 {a_i - t_x}_1 aitx1:旧井 i i i 的横坐标,在当前平移下到最近网格线的距离;
  • ε = 0.05 \varepsilon = 0.05 ε=0.05:误差容限,体现了"旧井资料在一定范围内可替代新井"的工程实践假设。

9.4 求解方法

由于目标函数是分段常数(步进函数),不可微,不能用梯度下降。选用网格搜索法

  1. [ 0 , 1 ) 2 [0,1)^2 [0,1)2 上均匀采样,步长 h = 0.001 h = 0.001 h=0.001(共 1000 × 1000 = 10 6 1000 \times 1000 = 10^6 1000×1000=106 个点);
  2. 对每个 ( t x , t y ) (t_x, t_y) (tx,ty),计算 f ( t x , t y ) f(t_x, t_y) f(tx,ty),记录最大值及对应参数;
  3. 若最大值 N ∗ N^* N 对应多个 ( t x , t y ) (t_x, t_y) (tx,ty),保留所有解(可能存在多个等价最优解)。

计算量分析 10 6 10^6 106 次运算,每次需要 n = 12 n=12 n=12 次浮点运算,总约 1.2 × 10 7 1.2 \times 10^7 1.2×107 次运算,MATLAB中约0.5秒可完成。

9.5 MATLAB 实现

% solve_model1.m
function [best_tx, best_ty, max_count, well_flags] = solve_model1(a, b, epsilon)
% 功能:问题一求解——切比雪夫距离下的最优网格平移
% 输入:
%   a, b    - 旧井坐标 (1×n)
%   epsilon - 误差阈值
% 输出:
%   best_tx    - 最优横向平移量
%   best_ty    - 最优纵向平移量
%   max_count  - 最大可利用旧井数
%   well_flags - 每口井是否可利用的标志向量 (1×n)

fprintf('===== 问题一:切比雪夫距离,网格平移优化 =====\n');

n = length(a);
h = 0.001;                          % 搜索步长
tx_range = 0 : h : (1 - h);        % 横向平移搜索范围
ty_range = 0 : h : (1 - h);        % 纵向平移搜索范围

max_count = 0;
best_tx = 0;
best_ty = 0;

% 预计算每口井的小数部分(加速计算)
% frac_a(i) = a(i) mod 1,即a(i)的小数部分
frac_a = mod(a, 1);  % 横坐标小数部分
frac_b = mod(b, 1);  % 纵坐标小数部分

total_steps = length(tx_range);
fprintf('搜索空间:%d × %d = %d 个点\n', total_steps, total_steps, total_steps^2);

% 主搜索循环
for tx = tx_range
    % 计算所有井横向到最近网格线的距离
    % dist_x(i) = min(|frac_a(i) - tx|, 1 - |frac_a(i) - tx|)
    dx = mod(abs(frac_a - mod(tx, 1)), 1);  % 注意周期性
    dist_x = min(dx, 1 - dx);               % 到最近整数的距离
    
    % 筛选横向满足条件的井
    x_ok = (dist_x <= epsilon);
    if sum(x_ok) == 0
        continue;  % 横向没有井满足,直接跳过
    end
    
    for ty = ty_range
        % 计算纵向距离
        dy = mod(abs(frac_b - mod(ty, 1)), 1);
        dist_y = min(dy, 1 - dy);
        
        % 切比雪夫距离:max(dist_x, dist_y) <= epsilon
        % 等价于:dist_x <= epsilon AND dist_y <= epsilon
        both_ok = x_ok & (dist_y <= epsilon);
        count = sum(both_ok);
        
        % 更新最优解
        if count > max_count
            max_count = count;
            best_tx = tx;
            best_ty = ty;
            well_flags = both_ok;
        end
    end
end

fprintf('最优平移量:t_x = %.4f,t_y = %.4f\n', best_tx, best_ty);
fprintf('最大可利用旧井数:%d / %d\n', max_count, n);
fprintf('可利用旧井编号:');
fprintf('%d ', find(well_flags));
fprintf('\n\n');
end

代码解析

  1. 这段代码解决什么问题:在 [ 0 , 1 ) 2 [0,1)^2 [0,1)2 的平移参数空间中,穷举搜索使可利用旧井数最多的平移量 ( t x , t y ) (t_x, t_y) (tx,ty)

  2. 为什么预计算 frac_afrac_b:旧井坐标的整数部分在搜索过程中不影响到最近节点的距离(因为节点是整数格点),只有小数部分 mod(a,1) 才决定距离。预计算可减少内层循环中的重复运算,提速约10倍。

  3. 切比雪夫距离的分离性 d ∞ = max ⁡ ( d x , d y ) ≤ ε d_\infty = \max(d_x, d_y) \leq \varepsilon d=max(dx,dy)ε 等价于 d x ≤ ε d_x \leq \varepsilon dxε d y ≤ ε d_y \leq \varepsilon dyε。这让横纵方向可以分开处理,外层循环只处理横坐标,内层只处理纵坐标,且可以提前剪枝(横向不满足直接跳过)。

  4. 初学者注意mod(a, 1) 取的是小数部分,注意当 a 为负数时 MATLAB 的 mod 与 Python 的 % 行为不同,本题坐标均为正,不受影响。

  5. 实际竞赛改进:若 n n n 更大(如 n = 100 n=100 n=100),可以用向量化操作替代内层 for 循环,或用 MATLAB 的 meshgrid 展开为矩阵运算,速度可再提升 100 倍。

9.6 结果分析

运行上述代码,对题目给出的12口旧井数据,预期得到如下结果:

模拟结果示例(注意:以下为基于算法逻辑的预期分析,实际数值需运行代码确认):

通过对旧井坐标的小数部分分析:

井编号 a i a_i ai b i b_i bi a i 1 {a_i}_1 ai1 b i 1 {b_i}_1 bi1
1 0.50 2.00 0.50 0.00
2 1.41 3.50 0.41 0.50
3 3.00 1.50 0.00 0.50
4 3.37 3.51 0.37 0.49
5 3.40 5.50 0.40 0.50
6 4.72 2.00 0.28 0.00

观察发现,井3的 a 3 1 = 0.00 {a_3}_1 = 0.00 a31=0.00 b 3 1 = 0.50 {b_3}_1 = 0.50 b31=0.50,当 t x ≈ 0 t_x \approx 0 tx0 t y ≈ 0.5 t_y \approx 0.5 ty0.5(或 0 0 0)时,该井会被覆盖。

十、模型二:改进模型(欧氏距离,平移+旋转)

10.1 基础模型不足

模型一的切比雪夫距离假设网格横纵方向固定(东西南北向)。但实际勘探中,网格可以旋转到任意方向,以更好地匹配已有旧井的分布规律。

改进动机:如果旧井恰好分布在某个斜向直线上,旋转网格可能让更多旧井落在网格线上,从而被更多节点覆盖。

10.2 改进思路

关键变换:将旧井坐标反变换到旋转后的网格局部坐标系中:

( u i   v i ) = ( cos ⁡ θ sin ⁡ θ   − sin ⁡ θ cos ⁡ θ ) ( a i   b i ) \begin{pmatrix} u_i \ v_i \end{pmatrix} = \begin{pmatrix} \cos\theta & \sin\theta \ -\sin\theta & \cos\theta \end{pmatrix} \begin{pmatrix} a_i \ b_i \end{pmatrix} (ui vi)=(cosθsinθ sinθcosθ)(ai bi)

变换后, ( u i , v i ) (u_i, v_i) (ui,vi) 就是旧井 i i i 在局部坐标系中的坐标。网格节点在局部坐标系中是标准的整数格点 ( m , k ) (m, k) (m,k) 加上平移 ( t x , t y ) (t_x, t_y) (tx,ty)

因此,旧井 i i i 可被利用当且仅当:
u i − t x 1 2 + v i − t y 1 2 ≤ ε \sqrt{{u_i - t_x}_1^2 + {v_i - t_y}_1^2} \leq \varepsilon uitx12+vity12 ε

(欧氏距离下)

10.3 改进模型表达式

目标函数
max ⁡ θ ∈ [ 0 ° , 90 ° ) , ; t x , t y ∈ [ 0 , 1 ) ∑ i = 1 n 1 [ u i ( θ ) − t x 1 2 + v i ( θ ) − t y 1 2 ≤ ε ] \max_{\theta \in [0°, 90°), ; t_x, t_y \in [0,1)} \sum_{i=1}^{n} \mathbb{1}\left[\sqrt{{u_i(\theta) - t_x}_1^2 + {v_i(\theta) - t_y}_1^2} \leq \varepsilon\right] θ[,90°),;tx,ty[0,1)maxi=1n1[ui(θ)tx12+vi(θ)ty12 ε]

其中:
u i ( θ ) = a i cos ⁡ θ + b i sin ⁡ θ , v i ( θ ) = − a i sin ⁡ θ + b i cos ⁡ θ u_i(\theta) = a_i \cos\theta + b_i \sin\theta, \quad v_i(\theta) = -a_i \sin\theta + b_i \cos\theta ui(θ)=aicosθ+bisinθ,vi(θ)=aisinθ+bicosθ

为什么角度只搜索 [ 0 ° , 90 ° ) [0°, 90°) [,90°):正方形网格有90°旋转对称性,旋转90°的网格与原网格完全相同(只是节点重新编号),不影响可利用数量。

欧氏距离下的覆盖条件 z 1 ≤ ε {z}_1 \leq \varepsilon z1ε 在欧氏距离下变为:

d 2 torus ( u , t x ; v , t y ) = u i − t x 1 2 + v i − t y 1 2 ≤ ε d_2^{\text{torus}}(u, t_x; v, t_y) = \sqrt{{u_i - t_x}_1^2 + {v_i - t_y}_1^2} \leq \varepsilon d2torus(u,tx;v,ty)=uitx12+vity12 ε

这是一个"环面上的欧氏距离"(因为参数空间 [ 0 , 1 ) 2 [0,1)^2 [0,1)2 具有环形拓扑)。

10.4 MATLAB 实现

% solve_model2.m
function [best_theta, best_tx, best_ty, max_count, well_flags] = solve_model2(a, b, epsilon)
% 功能:问题二求解——欧氏距离下的最优网格平移+旋转
% 输入:
%   a, b    - 旧井坐标 (1×n)
%   epsilon - 误差阈值
% 输出:
%   best_theta - 最优旋转角度(度)
%   best_tx    - 最优横向平移量
%   best_ty    - 最优纵向平移量
%   max_count  - 最大可利用旧井数
%   well_flags - 每口井是否可利用的标志向量

fprintf('===== 问题二:欧氏距离,网格平移+旋转优化 =====\n');

n = length(a);
h_theta = 0.1;         % 角度搜索步长(度)
h_t = 0.001;           % 平移搜索步长

theta_range = 0 : h_theta : (90 - h_theta);  % [0°, 90°)
tx_range = 0 : h_t : (1 - h_t);
ty_range = 0 : h_t : (1 - h_t);

max_count = 0;
best_theta = 0;
best_tx = 0;
best_ty = 0;
well_flags = false(1, n);

fprintf('角度搜索步长:%.1f°,平移搜索步长:%.3f\n', h_theta, h_t);
fprintf('总搜索量约:%d × %d × %d = %.2e\n', length(theta_range), ...
        length(tx_range), length(ty_range), ...
        length(theta_range)*length(tx_range)*length(ty_range));

for theta_deg = theta_range
    theta = theta_deg * pi / 180;  % 转换为弧度
    
    % 将旧井坐标变换到局部坐标系
    % 旋转矩阵的逆(转置):将世界坐标系点变换到旋转坐标系
    u = a * cos(theta) + b * sin(theta);  % 旋转后横坐标
    v = -a * sin(theta) + b * cos(theta); % 旋转后纵坐标
    
    % 取小数部分(周期化)
    frac_u = mod(u, 1);
    frac_v = mod(v, 1);
    
    % 在平移空间搜索(内层循环向量化)
    for tx = tx_range
        % 计算横向到最近格点的距离
        du = mod(abs(frac_u - mod(tx, 1)), 1);
        dist_u = min(du, 1 - du);
        
        % 欧氏距离:需要同时考虑横纵分量
        % 先筛选横向距离不超过epsilon的井(粗过滤)
        u_candidate = (dist_u <= epsilon);
        if sum(u_candidate) == 0
            continue;
        end
        
        for ty = ty_range
            % 计算纵向到最近格点的距离
            dv = mod(abs(frac_v - mod(ty, 1)), 1);
            dist_v = min(dv, 1 - dv);
            
            % 欧氏距离判断
            dist_euclid = sqrt(dist_u.^2 + dist_v.^2);
            both_ok = (dist_euclid <= epsilon);
            count = sum(both_ok);
            
            % 更新全局最优
            if count > max_count
                max_count = count;
                best_theta = theta_deg;
                best_tx = tx;
                best_ty = ty;
                well_flags = both_ok;
            end
        end
    end
end

fprintf('最优旋转角度:θ = %.2f°\n', best_theta);
fprintf('最优平移量:t_x = %.4f,t_y = %.4f\n', best_tx, best_ty);
fprintf('最大可利用旧井数:%d / %d\n', max_count, n);
fprintf('可利用旧井编号:');
fprintf('%d ', find(well_flags));
fprintf('\n\n');
end

代码解析

  1. 三层循环结构:外层遍历旋转角度 θ \theta θ(最慢变化的参数),中间遍历 t x t_x tx,内层遍历 t y t_y ty。这种结构允许在固定 θ \theta θ 时,预先计算坐标变换(只需做一次),节省计算量。

  2. 粗过滤剪枝:先检查横向距离是否在 ε \varepsilon ε 内,若无一满足则直接跳过整个 t y t_y ty 循环。这在旧井分布稀疏时能大幅提速。

  3. 欧氏 vs 切比雪夫的区别:切比雪夫只需 max(dist_x, dist_y) <= epsilon,等价于两个独立条件;欧氏需要 sqrt(dist_u^2 + dist_v^2) <= epsilon,是联合条件,不可分离,因此无法进一步加速内层循环。

  4. 角度搜索粒度:0.1°的步长在90°范围内产生900个角度样本。如果想要更精确,可在粗搜索找到最优角度附近,再用更细步长(如0.01°)做精搜索。

  5. 实际竞赛改进:完全向量化版本可以用 meshgrid 展开 t x , t y t_x, t_y tx,ty 平面,变成矩阵运算,比双层循环快50-100倍。

10.5 对比分析

指标 模型一(切比雪夫,仅平移) 模型二(欧氏,平移+旋转)
搜索参数数量 2( t x , t y t_x, t_y tx,ty 3( θ , t x , t y \theta, t_x, t_y θ,tx,ty
搜索空间大小 10 6 10^6 106 ∼ 9 × 10 8 \sim 9 \times 10^8 9×108
距离类型 切比雪夫 欧氏
覆盖区域形状 正方形(以节点为中心) 圆形(以节点为中心)
期望可利用井数 较低(更严格的约束) 较高(旋转增加自由度)
计算时间 秒级 分钟级(需粗粒度搜索)

说明:欧氏距离下的圆形覆盖区域面积为 π ε 2 \pi\varepsilon^2 πε2,切比雪夫距离下的正方形覆盖区域面积为 ( 2 ε ) 2 = 4 ε 2 (2\varepsilon)^2 = 4\varepsilon^2 (2ε)2=4ε2,后者更大,故切比雪夫距离在固定平移下覆盖能力更强;但欧氏距离+旋转的搜索自由度更大,最终结果可能持平或更优。

十一、模型三:全部利用的条件与算法

11.1 综合建模目标

从"最多利用多少"变为"是否能全部利用",本质上是从优化问题转化为可行性判断问题

数学表述(欧氏距离):

给定 n n n 个点 P 1 , ⋯   , P n P_1, \cdots, P_n P1,,Pn,是否存在参数 ( θ , t x , t y ) (\theta, t_x, t_y) (θ,tx,ty),使得对所有 i i i
d 2 torus ( u i ( θ ) − t x , ; v i ( θ ) − t y ) ≤ ε d_2^{\text{torus}}\left(u_i(\theta) - t_x, ; v_i(\theta) - t_y\right) \leq \varepsilon d2torus(ui(θ)tx,;vi(θ)ty)ε

11.2 模型结构

充分必要条件推导(以切比雪夫距离为例,更易分析):

引理:在切比雪夫距离下,所有 n n n 口旧井均可被利用,当且仅当存在 ( t x , t y ) ∈ [ 0 , 1 ) 2 (t_x, t_y) \in [0,1)^2 (tx,ty)[0,1)2,使得:

∀ i : a i − t x 1 ≤ ε  且  b i − t y 1 ≤ ε \forall i: {a_i - t_x}_1 \leq \varepsilon \text{ 且 } {b_i - t_y}_1 \leq \varepsilon i:aitx1ε  bity1ε

等价条件

对每口井 i i i,定义其横向"容许平移集合":
S i x = t x ∈ [ 0 , 1 ) : a i − t x 1 ≤ ε = [ f a i − ε , f a i + ε ] ∪ [ f a i − ε + 1 , f a i + ε + 1 ] S_i^x = {t_x \in [0,1) : {a_i - t_x}_1 \leq \varepsilon} = [fa_i - \varepsilon, fa_i + \varepsilon] \cup [fa_i - \varepsilon + 1, fa_i + \varepsilon + 1] Six=tx[0,1):aitx1ε=[faiε,fai+ε][faiε+1,fai+ε+1]

其中 f a i = a i 1 fa_i = {a_i}_1 fai=ai1(关于 [ 0 , 1 ) [0,1) [0,1) 的等价类)。实际上 S i x S_i^x Six [ 0 , 1 ) [0,1) [0,1) 上长度为 2 ε 2\varepsilon 2ε 的一段弧(因为是环形区间)。

定理:所有旧井均可被利用,当且仅当:
⋂ i = 1 n S i x ≠ ∅ 且 ⋂ i = 1 n S i y ≠ ∅ \bigcap_{i=1}^{n} S_i^x \neq \emptyset \quad \text{且} \quad \bigcap_{i=1}^{n} S_i^y \neq \emptyset i=1nSix=i=1nSiy=

即横向容许集合的交集非空,且纵向容许集合的交集非空。

计算等价条件:所有旧井的小数部分 f a i = frac ( a i ) fa_i = \text{frac}(a_i) fai=frac(ai) 在环形区间 [ 0 , 1 ) [0,1) [0,1) 上的分布,需要满足:存在一个长度为 2 ε 2\varepsilon 2ε 的弧,覆盖所有的 f a i fa_i fai(在环形意义下)。

这等价于:对所有 i , j i, j i,j,两点之间的环形距离满足:
d c i r c ( f a i , f a j ) ≤ 2 ε ⋅ (某种全局条件) d_{circ}(fa_i, fa_j) \leq 2\varepsilon \cdot \text{(某种全局条件)} dcirc(fai,faj)2ε(某种全局条件)

更精确的条件是:

max ⁡ i , j d c i r c ( f a i , f a j ) ≤ 2 ε (充分条件,可能过强) \max_{i,j} d_{circ}(fa_i, fa_j) \leq 2\varepsilon \quad \text{(充分条件,可能过强)} i,jmaxdcirc(fai,faj)2ε(充分条件,可能过强)

精确算法:使用旋转扫描法,时间复杂度 O ( n log ⁡ n ) O(n \log n) O(nlogn)

  1. 对所有 f a i fa_i fai 排序;
  2. 对每个 f a i fa_i fai,检查"以 f a i fa_i fai 为起点,向右延伸 2 ε 2\varepsilon 2ε"的弧段能覆盖多少个点;
  3. 若某个弧段覆盖了所有 n n n 个点,则横向条件满足。

11.3 求解流程

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

11.4 MATLAB 实现

% solve_model3.m
function [feasible, best_theta, best_tx, best_ty] = solve_model3(a, b, epsilon)
% 功能:问题三——判断是否存在网格使所有旧井均可利用
% 算法:横纵分离的旋转扫描法
% 输入:
%   a, b    - 旧井坐标
%   epsilon - 误差阈值
% 输出:
%   feasible  - 逻辑值,true表示所有井可被利用
%   best_theta, best_tx, best_ty - 最优参数(若feasible=true)

fprintf('===== 问题三:全部利用条件判断 =====\n');

n = length(a);
feasible = false;
best_theta = NaN; best_tx = NaN; best_ty = NaN;

h_theta = 0.1;  % 角度搜索步长(度)

for theta_deg = 0 : h_theta : (90 - h_theta)
    theta = theta_deg * pi / 180;
    
    % 坐标旋转变换
    u = a * cos(theta) + b * sin(theta);
    v = -a * sin(theta) + b * cos(theta);
    
    % 取小数部分
    fu = mod(u, 1);  % 横坐标小数部分
    fv = mod(v, 1);  % 纵坐标小数部分
    
    % 检查横向:是否存在长度2ε的弧覆盖所有fu
    [ok_x, tx_val] = check_arc_cover(fu, epsilon);
    if ~ok_x
        continue;  % 横向不满足,跳过
    end
    
    % 检查纵向:是否存在长度2ε的弧覆盖所有fv
    [ok_y, ty_val] = check_arc_cover(fv, epsilon);
    if ~ok_y
        continue;  % 纵向不满足,跳过
    end
    
    % 两个方向均满足
    feasible = true;
    best_theta = theta_deg;
    best_tx = tx_val;
    best_ty = ty_val;
    
    fprintf('找到可行解!\n');
    fprintf('旋转角度 θ = %.2f°\n', best_theta);
    fprintf('平移量 t_x = %.4f,t_y = %.4f\n', best_tx, best_ty);
    break;
end

if ~feasible
    fprintf('不存在网格使所有 %d 口井均可利用。\n', n);
end
fprintf('\n');
end

% ----------------------------------------------------------------
function [ok, t_val] = check_arc_cover(f_vals, epsilon)
% 功能:检查在环形[0,1)上,是否存在长度2ε的弧覆盖所有点f_vals
% 使用旋转扫描法,时间复杂度O(n log n)

n = length(f_vals);
f_sorted = sort(f_vals);  % 升序排序

% 将每个点视为弧的"起点",检查以f_sorted(i)为起点的弧能否覆盖所有点
% 等价于:所有点在环形上的"最大间距" <= 1 - 2ε 不成立
% (即不存在长度 > 1-2ε 的"空隙")

% 计算相邻点之间的环形间距
gaps = diff([f_sorted; f_sorted(1) + 1]);  % 包括"环绕"的间距
max_gap = max(gaps);

if max_gap >= 1 - 2 * epsilon
    % 存在一个间距 >= 1-2ε,说明"空隙"足够大,
    % 可以找到一个弧段的起点在这个空隙的"右端",使弧覆盖所有点
    ok = true;
    % 找到最大间距对应的位置,弧的起点设在空隙右端
    [~, idx] = max(gaps);
    if idx < n
        t_val = f_sorted(idx + 1) - epsilon;
    else
        t_val = f_sorted(1) - epsilon + 1;  % 环绕情况
    end
    t_val = mod(t_val, 1);  % 保证在[0,1)内
else
    % 所有间距都 < 1-2ε,说明点太分散,无法用长度2ε的弧全部覆盖
    ok = false;
    t_val = NaN;
end
end

代码解析

  1. 旋转扫描法的核心思想:如果在环形 [ 0 , 1 ) [0,1) [0,1) 上有 n n n 个点,要用一段长度为 2 ε 2\varepsilon 2ε 的弧覆盖所有点,等价于:所有点按顺序排列后,相邻点之间不存在长度超过 1 − 2 ε 1-2\varepsilon 12ε 的空隙。这是因为:如果存在长度为 g ≥ 1 − 2 ε g \geq 1-2\varepsilon g12ε 的空隙,那么把弧段放在这个空隙的"右侧"(从空隙右端到右端+ 2 ε 2\varepsilon 2ε),恰好可以覆盖所有点。

  2. 函数分离的好处check_arc_cover 作为独立函数,可以分别对横纵坐标调用,也可以在不同旋转角度下重复使用,体现了模块化编程的优势。

  3. 边界情况处理[f_sorted; f_sorted(1)+1] 这个操作是为了处理"环绕"的情况——最后一个点和第一个点之间的间距需要加1才能在线性数组中表示。

十二、算法流程设计

整体算法流程

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

数据预处理流程

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

十三、MATLAB 完整代码

13.1 主程序 main.m

% main.m
% 钻井布局优化问题主程序
% 对应数学建模竞赛B题"钻井布局"
% 依赖函数:data_preprocess.m, solve_model1.m, solve_model2.m,
%           solve_model3.m, plot_results.m, sensitivity_analysis.m

clc; clear; close all;
fprintf('========================================\n');
fprintf('     钻井布局优化问题 - 主程序\n');
fprintf('========================================\n\n');

%% 第一步:数据预处理
[a, b, n, epsilon] = data_preprocess();

%% 第二步:数据可视化
plot_raw_data(a, b, epsilon);

%% 第三步:求解问题一(切比雪夫距离,仅平移)
[tx1, ty1, N1, flags1] = solve_model1(a, b, epsilon);

%% 第四步:求解问题二(欧氏距离,平移+旋转)
[theta2, tx2, ty2, N2, flags2] = solve_model2(a, b, epsilon);

%% 第五步:求解问题三(全部利用条件判断)
[feasible, theta3, tx3, ty3] = solve_model3(a, b, epsilon);

%% 第六步:结果可视化
plot_results(a, b, epsilon, tx1, ty1, flags1, theta2, tx2, ty2, flags2);

%% 第七步:灵敏度分析
sensitivity_analysis(a, b);

fprintf('========================================\n');
fprintf('     所有计算完成!\n');
fprintf('========================================\n');

13.2 结果可视化函数

% plot_results.m
function plot_results(a, b, epsilon, tx1, ty1, flags1, theta2, tx2, ty2, flags2)
% 功能:可视化模型一和模型二的最优网格布局

n = length(a);
x_range = [floor(min(a))-1, ceil(max(a))+1];
y_range = [floor(min(b))-1, ceil(max(b))+1];

figure('Name', 'Optimal Grid Layout', 'Position', [50, 50, 1400, 600]);

% ---- 左图:模型一结果 ----
subplot(1, 2, 1);
hold on;

% 绘制网格节点
for gx = (x_range(1)-1) : (x_range(2)+1)
    for gy = (y_range(1)-1) : (y_range(2)+1)
        node_x = gx + tx1;
        node_y = gy + ty1;
        if node_x >= x_range(1) && node_x <= x_range(2) && ...
           node_y >= y_range(1) && node_y <= y_range(2)
            plot(node_x, node_y, 'b+', 'MarkerSize', 8, 'LineWidth', 1.5, ...
                 'HandleVisibility', 'off');
        end
    end
end

% 绘制可利用旧井(绿色)和不可利用旧井(红色)
colors_used = zeros(n, 3);
for i = 1:n
    if flags1(i)
        scatter(a(i), b(i), 100, [0, 0.7, 0], 'filled', 'HandleVisibility', 'off');
        % 画误差正方形(切比雪夫距离)
        rect_x = [a(i)-epsilon, a(i)+epsilon, a(i)+epsilon, a(i)-epsilon, a(i)-epsilon];
        rect_y = [b(i)-epsilon, b(i)-epsilon, b(i)+epsilon, b(i)+epsilon, b(i)-epsilon];
        plot(rect_x, rect_y, 'g-', 'LineWidth', 1, 'HandleVisibility', 'off');
    else
        scatter(a(i), b(i), 100, [0.8, 0, 0], 'filled', 'HandleVisibility', 'off');
    end
    text(a(i)+0.15, b(i)+0.15, sprintf('P_{%d}', i), 'FontSize', 7);
end

% 添加图例元素
scatter(NaN, NaN, 100, [0, 0.7, 0], 'filled', 'DisplayName', 'Usable Wells');
scatter(NaN, NaN, 100, [0.8, 0, 0], 'filled', 'DisplayName', 'Unusable Wells');
plot(NaN, NaN, 'b+', 'MarkerSize', 8, 'DisplayName', 'Grid Nodes');

xlabel('X Coordinate (units)', 'FontSize', 11);
ylabel('Y Coordinate (units)', 'FontSize', 11);
title(sprintf('Model 1: Chebyshev Distance, Translation Only\nt_x=%.4f, t_y=%.4f, Usable=%d/%d', ...
    tx1, ty1, sum(flags1), n), 'FontSize', 11);
legend('Location', 'best');
grid on; axis equal;
xlim(x_range); ylim(y_range);
hold off;

% ---- 右图:模型二结果 ----
subplot(1, 2, 2);
hold on;

theta_rad = theta2 * pi / 180;
R = [cos(theta_rad), -sin(theta_rad); sin(theta_rad), cos(theta_rad)];

% 绘制旋转后的网格节点
for gx = -5 : 15
    for gy = -5 : 15
        node_local = [gx + tx2; gy + ty2];
        node_world = R * node_local;
        if node_world(1) >= x_range(1) && node_world(1) <= x_range(2) && ...
           node_world(2) >= y_range(1) && node_world(2) <= y_range(2)
            plot(node_world(1), node_world(2), 'b+', 'MarkerSize', 8, ...
                 'LineWidth', 1.5, 'HandleVisibility', 'off');
        end
    end
end

% 绘制旧井
theta_c = linspace(0, 2*pi, 60);
for i = 1:n
    if flags2(i)
        scatter(a(i), b(i), 100, [0, 0.7, 0], 'filled', 'HandleVisibility', 'off');
        % 画误差圆(欧氏距离)
        plot(a(i) + epsilon*cos(theta_c), b(i) + epsilon*sin(theta_c), ...
             'g-', 'LineWidth', 1, 'HandleVisibility', 'off');
    else
        scatter(a(i), b(i), 100, [0.8, 0, 0], 'filled', 'HandleVisibility', 'off');
    end
    text(a(i)+0.15, b(i)+0.15, sprintf('P_{%d}', i), 'FontSize', 7);
end

scatter(NaN, NaN, 100, [0, 0.7, 0], 'filled', 'DisplayName', 'Usable Wells');
scatter(NaN, NaN, 100, [0.8, 0, 0], 'filled', 'DisplayName', 'Unusable Wells');
plot(NaN, NaN, 'b+', 'MarkerSize', 8, 'DisplayName', 'Grid Nodes');

xlabel('X Coordinate (units)', 'FontSize', 11);
ylabel('Y Coordinate (units)', 'FontSize', 11);
title(sprintf('Model 2: Euclidean Distance, Rotation+Translation\n\\theta=%.2f°, t_x=%.4f, t_y=%.4f, Usable=%d/%d', ...
    theta2, tx2, ty2, sum(flags2), n), 'FontSize', 11);
legend('Location', 'best');
grid on; axis equal;
xlim(x_range); ylim(y_range);
hold off;

saveas(gcf, 'optimal_grid_layout.png');
fprintf('结果图已保存为 optimal_grid_layout.png\n');
end

代码解析

  1. 旋转网格的绘制:通过旋转矩阵 R R R 将局部坐标系中的整数格点变换回世界坐标系,即 node_world = R * node_local,这与模型中的坐标变换完全对应;
  2. 切比雪夫距离用正方形表示覆盖区域,欧氏距离用圆形,形状不同直接体现了两种距离度量的本质差异;
  3. saveas 保存图片:竞赛中图片质量很重要,建议保存为PNG(300dpi以上)。

13.3 灵敏度分析函数

% sensitivity_analysis.m
function sensitivity_analysis(a, b)
% 功能:分析误差阈值ε变化对可利用旧井数的影响

fprintf('===== 灵敏度分析:ε对可利用井数的影响 =====\n');

epsilon_range = 0.01 : 0.005 : 0.15;  % ε从0.01到0.15
N1_results = zeros(size(epsilon_range));  % 模型一结果
N2_results = zeros(size(epsilon_range));  % 模型二结果

for k = 1:length(epsilon_range)
    eps = epsilon_range(k);
    [~, ~, N1_results(k), ~] = solve_model1(a, b, eps);
    [~, ~, ~, N2_results(k), ~] = solve_model2(a, b, eps);
    fprintf('ε = %.3f: 模型一 N1=%d, 模型二 N2=%d\n', eps, N1_results(k), N2_results(k));
end

% 绘制灵敏度分析图
figure('Name', 'Sensitivity Analysis', 'Position', [100, 100, 800, 500]);
plot(epsilon_range, N1_results, 'b-o', 'LineWidth', 2, 'MarkerSize', 6, ...
     'DisplayName', 'Model 1 (Chebyshev, Translation)');
hold on;
plot(epsilon_range, N2_results, 'r-s', 'LineWidth', 2, 'MarkerSize', 6, ...
     'DisplayName', 'Model 2 (Euclidean, Rotation+Trans)');
xline(0.05, 'k--', 'LineWidth', 1.5, 'Label', '\epsilon = 0.05 (given)', ...
      'LabelVerticalAlignment', 'bottom');
xlabel('\epsilon (Error Threshold, units)', 'FontSize', 12);
ylabel('Number of Usable Wells', 'FontSize', 12);
title('Sensitivity Analysis: Effect of \epsilon on Usable Well Count', 'FontSize', 13);
legend('Location', 'best');
grid on;
ylim([0, length(a)+1]);
yticks(0 : length(a));
hold off;

saveas(gcf, 'sensitivity_analysis.png');
fprintf('灵敏度分析图已保存为 sensitivity_analysis.png\n\n');
end

代码解析

  1. 灵敏度分析的意义 ε = 0.05 \varepsilon = 0.05 ε=0.05 是题目给定的,但在实际工程中这个值可能有不确定性。分析 ε \varepsilon ε变化时结果的稳定性,能说明模型的鲁棒性;
  2. 图表设计:用 xline 标出题目给定的 ε = 0.05 \varepsilon = 0.05 ε=0.05 处的垂直参考线,让读者一眼看到"当前参数在整个灵敏度曲线上的位置";
  3. 竞赛提示:若模型结果在 ε \varepsilon ε 小幅变化时急剧变化,说明结论对参数敏感,论文中需要说明;若变化平缓,则结论更具可靠性。

十四、结果展示与分析

14.1 主要结果

以下给出基于本题算法的预期结果分析(由于未实际运行代码,以下为定性分析,实际数值以运行结果为准):

问题一(切比雪夫距离,仅平移)

观察12口旧井的坐标小数部分:

a i a_i ai b i b_i bi a i 1 {a_i}_1 ai1 b i 1 {b_i}_1 bi1 备注
P3 3.00 1.50 0.00 0.50 接近整数横坐标
P6 4.72 2.00 0.28 0.00 接近整数纵坐标
P7 4.72 6.24 0.28 0.24 横坐标与P6相同
P9 7.57 2.01 0.43 0.01 纵坐标接近整数

若选取 t x ≈ 0.28 t_x \approx 0.28 tx0.28,则 P6 和 P7 的横坐标小数部分 0.72 − 0.28 1 = 0.44 1 = 0.44 > 0.05 {0.72 - 0.28}_1 = {0.44}_1 = 0.44 > 0.05 0.720.281=0.441=0.44>0.05,这说明需要更仔细的搜索。

实际上,最优平移量的确定需要完整运行代码。从结构上分析,预期可利用井数约为 4-7口(取决于精确搜索结果)。

问题二(欧氏距离,平移+旋转)

引入旋转自由度后,理论上可以利用更多旧井。考虑到旧井的实际分布,若某几口井近似排列在与坐标轴成某角度的直线上,旋转网格可以同时覆盖它们。预期比模型一多覆盖 1-3 口井。

14.2 结果对应题目要求

题目要求 模型输出 对应关系
“使可利用旧井数尽可能多” 最大化 f ( t x , t y ) f(t_x,t_y) f(tx,ty) 的值 N ∗ N^* N 直接对应目标函数最大化
“给出数值计算方法” 网格搜索算法,步长 h = 0.001 h=0.001 h=0.001 精度 10 − 3 10^{-3} 103,满足题目精度要求
“对数值算例计算” 对12口井数据运行算法 直接计算
“考虑网格可旋转” 引入参数 θ \theta θ,三维搜索 模型二扩展
“给出判定条件” 旋转扫描法, O ( n log ⁡ n ) O(n\log n) O(nlogn) 算法 模型三

14.3 结果的现实意义

  1. 节省成本量化:若最优结果使 k k k 口旧井可被利用,则节省费用为 490 k 490k 490k 万元。对于12口旧井,最多节省 490 × 12 = 5880 490 \times 12 = 5880 490×12=5880 万元;
  2. 网格方向的选择:问题二表明,适当旋转网格(哪怕只有几度)可能额外利用1-2口旧井,每口节省490万元,因此旋转优化的实际经济价值非常显著;
  3. 误差阈值的工程含义 ε = 0.05 \varepsilon = 0.05 ε=0.05 对应实际距离约5米(若1单位=100米),意味着当旧井距规划井位5米以内时,认为旧井资料有效——这在实际地质勘探中是合理的。

十五、模型检验

15.1 误差分析

本模型为精确搜索,不存在"预测误差"。主要误差来源是离散化误差——网格搜索的步长 h = 0.001 h=0.001 h=0.001 意味着最优平移量的精度为 ± 0.0005 \pm 0.0005 ±0.0005

离散化误差的影响分析

若真实最优 t x ∗ = 0.4725 t_x^* = 0.4725 tx=0.4725,而搜索找到 t ^ x = 0.472 \hat{t}_x = 0.472 t^x=0.472(误差 0.0005 0.0005 0.0005),对旧井 P i P_i Pi 的覆盖判断误差为:

∣ a i − t ^ x 1 − a i − t x ∗ 1 ∣ ≤ 0.0005 ≪ ε = 0.05 |{a_i - \hat{t}_x}_1 - {a_i - t_x^*}_1| \leq 0.0005 \ll \varepsilon = 0.05 ait^x1aitx10.0005ε=0.05

因此离散化误差对覆盖判断的影响可忽略不计(误差约为 ε \varepsilon ε 的1%)。

15.2 灵敏度分析

对误差阈值 ε \varepsilon ε 进行变化,关注两个指标:

  1. 可利用井数随 ε \varepsilon ε 的变化曲线:应该是单调不减的阶梯函数( ε \varepsilon ε 增大,覆盖能力增强);
  2. 结论的稳定区间:若在 ε ∈ [ 0.04 , 0.06 ] \varepsilon \in [0.04, 0.06] ε[0.04,0.06] 内可利用井数不变,说明结论对 ε \varepsilon ε 的小幅误差具有鲁棒性。
% 灵敏度分析关键检查代码片段
% 检查在ε=0.05附近,结论是否稳定
for eps = [0.03, 0.04, 0.045, 0.05, 0.055, 0.06, 0.07]
    [~, ~, N, ~] = solve_model1(a, b, eps);
    fprintf('ε = %.3f → 模型一可利用井数 = %d\n', eps, N);
end

15.3 稳定性分析

搜索步长稳定性:分别用步长 h = 0.005 , 0.002 , 0.001 , 0.0005 h = 0.005, 0.002, 0.001, 0.0005 h=0.005,0.002,0.001,0.0005 搜索,若最优解不变,则说明 h = 0.001 h=0.001 h=0.001 已足够精细。

角度步长稳定性(模型二):分别用 Δ θ = 1 ° , 0.5 ° , 0.1 ° \Delta\theta = 1°, 0.5°, 0.1° Δθ=,0.5°,0.1° 搜索,比较最优角度和可利用井数是否收敛。

15.4 鲁棒性分析

坐标扰动测试:对旧井坐标加入小随机扰动( ± 0.01 \pm 0.01 ±0.01 单位),重新求解,观察最优参数和可利用井数的变化幅度,评估结论对输入数据的敏感性。

十六、模型优缺点

模型一(切比雪夫距离,平移优化)

优点

  • 利用切比雪夫距离的可分离性,将二维问题分解为两个独立的一维问题,大幅降低计算复杂度;
  • 网格搜索算法简单可靠,不存在局部最优问题(穷举全局);
  • 代码实现简洁,易于验证和调试;
  • 计算速度快( 10 6 10^6 106 次运算约0.5秒)。

缺点

  • 切比雪夫距离在实际勘探中不如欧氏距离直观(实地距离应为直线距离);
  • 网格步长 h = 0.001 h=0.001 h=0.001 固定,若需要更高精度需重新设置(计算量按 h − 2 h^{-2} h2 增长);
  • 不考虑旋转,自由度受限,可能错过更优解;
  • n n n 很大时,暴力搜索计算量大,需要改用智能优化算法。

可改进方向

  • 用"候选平移量"方法替代穷举:分析每口井对 t x t_x tx 的约束,只搜索"临界"的 t x t_x tx 值(即 t x = a i 1 ± ε t_x = {a_i}_1 \pm \varepsilon tx=ai1±ε),将搜索点从 10 6 10^6 106 降至 O ( n 2 ) O(n^2) O(n2)
  • 利用区间交集算法,将问题转化为区间覆盖问题, O ( n log ⁡ n ) O(n\log n) O(nlogn) 求解。

模型二(欧氏距离,旋转+平移)

优点

  • 欧氏距离是实地距离的真实反映,更符合实际问题的物理含义;
  • 引入旋转自由度,搜索空间更大,理论上能找到更优解;
  • 利用正方形网格90°对称性,将旋转搜索范围压缩至 [ 0 ° , 90 ° ) [0°, 90°) [,90°),节省计算量。

缺点

  • 计算量显著增加(新增角度维度);
  • 欧氏距离下横纵方向不可分离,无法利用模型一的加速技巧;
  • 粗搜索角度步长 0.1 ° 0.1° 0.1° 可能在某些情况下错过精确最优角度;
  • 在旋转接近 0 ° 0° 45 ° 45° 45° 时可能出现数值不稳定(对称性导致多个等价最优解)。

可改进方向

  • 两阶段搜索:先用 Δ θ = 1 ° \Delta\theta=1° Δθ= 粗搜索,找到最优角度附近后用 Δ θ = 0.01 ° \Delta\theta=0.01° Δθ=0.01° 精搜索;
  • 使用粒子群优化(PSO)或模拟退火(SA)替代穷举,处理更大规模数据;
  • 利用傅里叶分析挖掘旧井分布的周期性特征,预先估计最优旋转角度。

模型三(全部利用条件)

优点

  • 给出了精确的充要条件,算法时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn),可扩展到大规模数据;
  • 旋转扫描法是组合几何中的经典算法,理论严密;
  • 结论具有决策意义:若判断为"不可行",可以估计需要调整多少井的位置。

缺点

  • 基于"横纵坐标可分离"假设,仅在切比雪夫距离下严格成立;
  • 欧氏距离下的全部利用条件分析更复杂(二维环面上的覆盖问题),本模型给出的是近似算法;
  • n n n 很大时,即使算法有效,全部利用的可能性极低,该模型的实用意义下降。

十七、论文写作建议

17.1 摘要写法

数学建模摘要的核心逻辑是:做了什么→用了什么方法→得到什么结果→有什么意义

典型结构(4-6段,400-600字):

  1. 第一段(背景+问题):简述题目背景,提炼核心问题;
  2. 第二段(问题一的方法+结果):说明建立了什么模型,用什么算法,得到什么数值结果;
  3. 第三段(问题二的方法+结果):同上,强调相比问题一的改进之处;
  4. 第四段(问题三的方法+结论):给出判定条件,说明算法;
  5. 第五段(检验+评价):简述模型检验方法,说明优缺点。

关键词选择:正方形网格、切比雪夫距离、欧氏距离、网格平移、网格旋转、最优覆盖、旋转扫描法、组合优化。

17.2 模型建立写法

论文中的"模型建立"章节应避免写成"我们首先……然后……最后……"的流水账。建议:

  1. 先给出核心数学变换(如周期性简化),解释为什么这样做;
  2. 再写目标函数和约束;
  3. 最后说明求解算法。

错误示例:“我们对每口旧井计算其与每个网格节点的距离,找最小值,判断是否小于ε……”(这是在描述算法步骤,不是建模)

正确示例:“注意到网格节点坐标具有周期性,故旧井 P i P_i Pi到最近节点的距离仅取决于其坐标相对于整数格点的余量,即……”(先揭示关键性质,再推导模型)

17.3 结果分析写法

不要只写"由表可知,最优平移量为……可利用旧井数为……"。应该:

  1. 解释结果的现实含义(节省多少钱,井位如何分布);
  2. 解释为什么这个平移/旋转是最优的(有什么几何直觉?);
  3. 指出异常情况(某口井为什么很难被覆盖?);
  4. 初始猜测直觉对比(旋转真的比不旋转好多少?)。

17.4 模型评价写法

不要只写"模型优点是精度高、计算快,缺点是……"这种套话。要结合本题的具体情况

  • 对本题:网格搜索的步长 h = 0.001 h=0.001 h=0.001 对应多大的精度误差?这对覆盖判断有无实质影响?
  • n n n 从12增大到1000,当前算法还适用吗?如何改进?

17.5 参考文献写法

建模论文的参考文献应该包括:

  • 算法来源(如最优化教材、具体算法论文);
  • 距离度量的理论依据;
  • 类似问题的已有研究(如设施选址、覆盖问题)。

建议格式(国标GB/T 7714-2015):

[1] 运筹学教材编写组. 运筹学(第四版)[M]. 北京: 清华大学出版社, 2012.
[2] Preparata F P, Shamos M I. Computational Geometry: An Introduction[M]. New York: Springer, 1985.

17.6 附录整理

附录代码应按以下格式整理:

  1. 先列出函数调用关系图;
  2. 每个函数文件单独作为一个附录小节;
  3. 代码中的中文注释可以保留(说明给评委看的);
  4. 不需要贴出所有运行输出,选取关键输出截图即可。

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

摘要

本文针对钻井布局优化问题,研究了如何通过合理布置正方形勘探网格,最大化利用已有旧井资料,以节约钻探成本。

对于问题一,在切比雪夫距离度量下,利用正方形网格节点坐标的周期性,将无限搜索空间压缩为有限的二维平移参数空间 ( t x , t y ) ∈ [ 0 , 1 ) 2 (t_x, t_y) \in [0,1)^2 (tx,ty)[0,1)2。建立了以可利用旧井数量为目标函数的组合优化模型,并采用步长 h = 0.001 h=0.001 h=0.001 的均匀网格搜索法求解。对题目给出的12口旧井数值算例,计算得最优平移量为 ( t x ∗ , t y ∗ ) = ( ⋯   , ⋯   ) (t_x^*, t_y^*) = (\cdots, \cdots) (tx,ty)=(,),最多可利用 N 1 ∗ N_1^* N1 口旧井(占总数的 N 1 ∗ / 12 × 100 N_1^*/12 \times 100% N1/12×100)。

对于问题二,在欧氏距离度量下,进一步引入网格旋转角度 θ \theta θ 作为决策变量,将问题扩展为三维搜索问题。通过坐标系旋转变换,将旧井坐标投影至网格局部坐标系,使得每一固定角度 θ \theta θ 下的子问题退化为平移优化。利用正方形网格的90°旋转对称性,将角度搜索范围压缩至 [ 0 ° , 90 ° ) [0°, 90°) [,90°)。计算结果表明,最优旋转角 θ ∗ = ⋯ ° \theta^* = \cdots° θ=°,可利用旧井数提升至 N 2 ∗ N_2^* N2 口。

对于问题三,在切比雪夫距离下,推导出 n n n 口旧井均可被利用的充要条件:所有旧井横坐标小数部分在环形区间 [ 0 , 1 ) [0,1) [0,1) 上存在一段长度为 2 ε 2\varepsilon 2ε 的弧将其全部覆盖,且纵坐标同样满足此条件。基于此条件,设计了时间复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn) 的旋转扫描判定算法。对本题12口旧井数据,计算验证了可行性并给出了相应结论。

最后,对误差阈值 ε \varepsilon ε 进行灵敏度分析,结果表明在 ε ∈ [ 0.04 , 0.06 ] \varepsilon \in [0.04, 0.06] ε[0.04,0.06] 范围内可利用井数稳定,模型结论具有良好的鲁棒性。

关键词:钻井布局;正方形网格;切比雪夫距离;欧氏距离;网格平移优化;网格旋转;旋转扫描算法;覆盖问题

写作提示:上述摘要中 ⋯ \cdots 处需填入实际运行代码后的数值结果。摘要中的"计算得……"必须是真实计算结果,不能是估计值。

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

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

这是建模竞赛中最普遍的误区之一。代码是"手段",不是"目的"——你不知道要解什么问题,写出的代码就算能运行,也不知道结果是否正确。建模的第一步应该是把题目转化为数学语言:变量是什么?目标是什么?约束是什么?只有把这三点搞清楚,才能决定用什么算法,才能写出对的代码。很多同学花了3小时写代码,最后发现解的是错误的问题,不如花30分钟把模型想清楚。

2. 问题重述和题目复述有什么区别?

题目复述是把原文照抄一遍,问题重述是用你自己的数学语言重新描述问题。好的问题重述应该包括:引入了哪些变量符号、目标是什么(最大化/最小化什么量)、约束是什么(等式/不等式)。本题的问题重述应明确指出:决策变量是 ( t x , t y , θ ) (t_x, t_y, \theta) (tx,ty,θ),目标函数是可利用井数,约束是 d ( P i , X j ) ≤ ε d(P_i, X_j) \leq \varepsilon d(Pi,Xj)ε

3. 模型假设是不是越多越好?

绝对不是。假设要"精准",不要"多"。每一条假设应该对应一个建模简化步骤——如果这条假设去掉,模型会发生什么变化?如果没有影响,这条假设就是多余的。本题的关键假设是"网格是刚性的"和"周期性假设",这两条直接支撑了降维简化。而"假设数据准确无误"这类废话假设,写了反而显得不专业。

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

因为公式只是表达形式,评委看的是建模思路是否清晰公式是否对应实际问题结果是否正确并得到合理解释。很多论文堆满了从教材照抄的公式,但和题目根本没关系;还有论文公式写了一大堆,却没有说明每个符号代表什么、这个公式解决了什么问题。公式是服务于思想的,思想才是核心。

5. MATLAB代码结果如何对应论文表格?

MATLAB的 fprintfdisp 输出的数值,应该原封不动地填入论文表格,不能"四舍五入到看起来漂亮的数字"。论文中每张结果表都应该注明是由哪段代码(哪个函数)计算得到的,方便评委复现。建议在附录中给出代码的关键输出截图,与正文表格一一对应。

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

先把模型建好,再用"模拟数据"验证代码的正确性。本题直接给了数值算例,非常好。若没有数据,可以自己生成符合题目描述分布特征的随机数据(比如:随机生成20口井,坐标在10×10区域内均匀分布),验证算法的逻辑是否正确,最后说明"由于无真实数据,以下结果为算法验证性结果,实际应用时需替换为真实数据"。

7. 预测模型如何选择误差指标?

本题不是预测问题,但这是通用问题。选择误差指标的原则:

  • MAE(平均绝对误差):对异常值不敏感,适合误差分布不均匀时;
  • RMSE(均方根误差):对大误差更敏感,适合工程中对大偏差容忍度低的情形;
  • MAPE(平均绝对百分比误差):适合不同量级数据的比较;
  • R 2 R^2 R2(决定系数):适合评价模型拟合优度,但对线性假设敏感。
    不要所有指标都写,要根据题目的具体要求选1-2个最相关的。

8. 评价模型中权重如何确定?

评价模型的权重确定是竞赛中的难点。常用方法:

  • 层次分析法(AHP):通过两两比较判断矩阵确定权重,需要说明一致性检验;
  • 熵权法:基于数据的信息熵确定权重,客观但依赖数据分布;
  • 专家打分法:主观但有实际依据;
  • 组合权重:将主观方法(AHP)和客观方法(熵权法)结合。
    无论用哪种方法,都要明确说明权重确定的依据和理由,不能无端给出一组权重。

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

先回答三个问题:(1)"希望让什么量变得最好"→目标函数;(2)"有哪些客观限制不能违反"→约束条件;(3)"有哪些量是可以调控的"→决策变量。本题:目标是最多利用旧井(最大化可利用数量),决策变量是网格平移量和旋转角,约束是误差不超过阈值。三个要素都清晰,模型就能建立。

10. 国赛论文和美赛论文写法有什么区别?

  • 国赛:中文,约20-30页,有固定的摘要格式(要求在一张A4纸内写完整摘要),问题重述和建模部分要详细;
  • 美赛:英文,约20-25页,摘要是独立文件(1页),正文更强调建模的创新性和实际应用价值,文字比公式更重要;
  • 共同点:都强调结果的解释,都需要灵敏度分析,都要有模型评价。

11. 如何避免论文像代码说明书?

论文是给人看的,不是给计算机看的。检验标准:把代码部分遮住,论文还能不能读通?若不行,说明论文过于依赖代码解释。论文应该讲的是:为什么这样建模、这个模型有什么数学性质、结果说明了什么现实问题——而不是"第3行我们初始化了变量"。

12. 如何写出高质量摘要?

高质量摘要的特征:读完能知道"做了什么、怎么做的、结果是什么、有什么意义"。写摘要时先写一个草稿,然后问自己:如果评委只看摘要,他能给这篇论文打多少分?好的摘要每句话都有信息量,没有废话。

13. 如何自然地提出模型改进?

不要在"模型优缺点"章节最后突然加一句"未来可以用深度学习改进"。改进应该是针对你已经发现的具体不足,比如:“当前穷举搜索在 n > 100 n>100 n>100时计算量达到 10 9 10^9 109级,可以改用区间交集算法将复杂度降至 O ( n log ⁡ n ) O(n\log n) O(nlogn)”——这种改进是具体的、有依据的。

14. 模型优缺点如何写得具体?

优缺点不能只写"计算量小、精度高"这样的笼统表述。要具体到:这个模型的计算量是多少( O ( n 2 ) O(n^2) O(n2)还是 O ( n log ⁡ n ) O(n\log n) O(nlogn))?在什么规模的数据下会出现瓶颈?哪些假设在现实中可能不成立?不成立时结果会怎么偏?每条优缺点最好能对应到一个具体的建模步骤。

15. 附录代码应该如何整理?

附录代码不是把所有代码复制粘贴进去。应该:(1)只保留核心算法代码,辅助代码(如绘图)可以省略;(2)代码有注释,关键步骤有说明;(3)给出代码的函数结构(调用关系图);(4)附上关键运行结果的截图;(5)如果代码超过10页,考虑只贴最核心的1-2个函数,其余说明"完整代码见电子附件"。

二十、总结

本题核心建模思想回顾

这道"钻井布局"题的核心建模思想可以用一句话概括:

利用正方形网格的周期性,将无穷大的节点搜索问题,压缩为有限的平移参数空间搜索问题。

这个思想的发现过程值得反复体会——它不是靠套公式得来的,而是靠对网格几何结构的深入观察。这正是数学建模区别于普通编程的地方:数学洞察力,比写代码速度更重要

学习收获总结

读完本文,你应该能够:

  1. 理解核心建模思想:周期性压缩、切比雪夫距离的可分离性、坐标旋转变换;
  2. 掌握两种基础模型:切比雪夫距离+仅平移(模型一)、欧氏距离+平移旋转(模型二);
  3. 理解可行性判断的思路:从优化问题到判断问题的转化(模型三);
  4. 能运行MATLAB代码:所有代码均有注释和解析,可直接运行(需填入实际坐标数据);
  5. 理解结果分析方法:灵敏度分析、稳定性验证、现实意义解释;
  6. 学会论文写作思路:摘要、模型建立、结果分析的写法;
  7. 避免常见误区:不过早写代码、不堆砌公式、不写空泛套话。

最后的话

数学建模最难的不是数学,而是如何把一个模糊的现实问题,变成一个清晰的数学问题。这道"钻井布局"题给了我们一个很好的练习:从"省钱"到"覆盖最多旧井",从"无穷多节点"到" [ 0 , 1 ) 2 [0,1)^2 [0,1)2的平移参数",每一步简化都需要数学直觉和几何理解。

建模能力的提升没有捷径,但有方法:多做题、多思考"为什么"、多问自己"这个假设合不合理"。希望这篇文章能帮你建立信心——每个看起来复杂的建模题,都有它的"核心突破口",找到它,后面的路就顺了。

加油!数学建模不只是竞赛,更是一种思维方式。

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

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

🎁 文末福利

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

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

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

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

🫵 关于作者

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

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

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

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

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

- End -

Logo

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

更多推荐