蓝桥杯国赛扩散题解析:从BFS模拟到曼哈顿距离判定的算法优化

发布时间:2026/8/28 4:48:47

蓝桥杯国赛扩散题解析:从BFS模拟到曼哈顿距离判定的算法优化
1. 项目概述从一道国赛真题看算法思维的本质看到“2020第十一届蓝桥杯决赛国赛题目 C B组B题扩散”这个标题很多参加过蓝桥杯的同学估计会心一笑或者心头一紧。这道题可以说是那一年国赛的一个标志性题目它不像某些纯数学题那样烧脑也不像某些大型模拟题那样繁琐但它精准地考察了选手对基础算法思想的理解、转化以及代码实现能力。题目本身描述了一个在无限大网格上的“扩散”过程初始有四个点每个时间单位会向上下左右四个方向扩散一格问经过2020个单位时间后有多少个格子被扩散到。听起来很简单甚至有点像一道BFS广度优先搜索的模板题但国赛的B题怎么可能让你轻易用模板套出来这里面藏着对时间与空间复杂度的深刻考量以及对问题本质的洞察力。今天我就以这道题为引子拆解一下面对这类“模拟扩散”问题时一个合格的竞赛选手应该如何思考从暴力模拟的陷阱到优化思路的诞生再到最终优雅的解法。无论你是正在备赛蓝桥杯还是想提升自己的算法思维相信这篇深度的复盘都能给你带来启发。2. 题目深度解析与核心矛盾2.1 问题重述与抽象建模我们先抛开代码把题目用更严谨的语言描述一遍这是解题的第一步也是避免理解偏差的关键。问题场景在一个无限的二维平面网格上每个格子的坐标用整数对(x, y)表示。在时间t0时有四个点被标记或者说被“感染”了点 A:(0, 0)点 B:(2020, 11)点 C:(11, 14)点 D:(2000, 2000)扩散规则从t0开始每一时刻t从0增长到2020所有已被标记的格子会同时向其上、下、左、右四个相邻的格子即(x1, y),(x-1, y),(x, y1),(x, y-1)进行扩散。新被扩散到的格子在下一个时刻也将具备扩散能力。求解目标求在t2020时刻结束时有多少个不同的格子曾被标记过即被扩散到过。关键抽象这个过程本质上是一个多源点、同步更新的广度优先搜索BFS。四个初始点就是四个源头扩散规则就是BFS中从当前节点探索其四邻域的过程时间t对应的就是BFS的层数或步数。我们要找的就是BFS进行2020步后访问到的所有节点的总数。2.2 暴力BFS模拟的陷阱与复杂度分析几乎所有选手的第一反应都是BFS模拟。思路非常直接用一个队列queue存储当前时刻所有已被标记的节点坐标(x, y)和其被标记的时间t。用一个集合set存储所有已被访问过的节点坐标用于去重。初始将四个源点(0,0,0),(2020,11,0),(11,14,0),(2000,2000,0)入队并加入已访问集合。当队列不为空时取出队首节点(x, y, t)。如果t 2020说明该节点是在第2020时刻才被首次访问的它已经没有时间再扩散了因此可以跳过其邻域的探索或者直接停止从该节点继续BFS。如果t 2020则遍历其四个邻居(nx, ny)如果(nx, ny)未被访问过则将其以时间t1入队并加入已访问集合。最后已访问集合的大小就是答案。这个思路正确吗完全正确。但它能运行出来吗在比赛环境下几乎不可能。我们来做一个粗略的复杂度估算。扩散是以曼哈顿距离为半径的菱形区域。从一个单源点扩散2020步覆盖的格子数大约是一个菱形的面积数量级在O(step^2)即大约4百万个格子具体是2*step*(step1)1。现在我们有四个源点它们扩散的区域会有大量重叠但即便我们乐观估计最终访问的节点总数N也在千万级别实际答案远小于此但当时在赛场上无法精确预知。空间复杂度存储千万级别的(x, y)对到集合中在C中即使使用std::unordered_set并自定义哈希内存消耗也非常巨大每个节点开销几十字节千万级别就是几百MB极易导致内存超限MLE。时间复杂度BFS每个节点都会出队一次并尝试访问其四个邻居。对于每个邻居需要在哈希集合中进行查找和插入操作。哈希操作的平均时间复杂度是O(1)但常数很大。千万级别的节点操作在比赛常见的2秒时间限制内几乎必然超时TLE。注意这里就是比赛策略的第一个分水岭。有经验的选手不会一头扎进编码实现而是会先进行数量级估算。看到step2020就应该立刻警惕O(N^2)或节点数巨大的模拟方法。蓝桥杯国赛的题目参数设计往往是有深意的2020这个数显然不是让你真的去模拟2020步。2.3 核心矛盾与优化方向定位所以我们遇到了核心矛盾问题模型BFS是清晰的但数据规模2020步使得直接模拟不可行。优化的方向必须围绕减少需要显式表示和访问的节点数量。方向一利用问题的对称性与数学性质直接计算覆盖面积。 这需要极强的数学功底去推导四个菱形区域并集的面积公式。考虑到源点坐标并不对称且重叠区域形状不规则这个方向非常困难几乎不是竞赛时限内能完成的。方向二优化BFS的表示与搜索方式。 这是更可行的思路。我们问自己BFS过程中我们真的需要存储每一个被访问的格子坐标吗我们是否可以用更紧凑的方式来表示“已被覆盖的区域”一个关键的观察是扩散过程只与曼哈顿距离有关。对于一个源点(sx, sy)在时间t时它能覆盖的所有格子恰好是满足曼哈顿距离|x - sx| |y - sy| t的所有点(x, y)。这个区域就是一个中心在(sx, sy)对角线长为2t的菱形。那么问题就转化为求平面上所有满足“到任意一个源点的曼哈顿距离 2020”的整数坐标点(x, y)的个数。这样一来我们就不再需要模拟“时间”这个维度了。我们只需要遍历一个“足够大”的矩形区域对区域内的每个点判断其到四个源点的最小曼哈顿距离是否小于等于2020。如果是则计数器加一。3. 高效算法设计与实现细节3.1 算法思路确立曼哈顿距离判定法基于上述分析我们确定最终算法确定遍历范围我们需要遍历一个包含所有可能被覆盖点的矩形区域。最保守的范围是以四个源点的坐标为基础分别向四个方向扩展2020个单位。即最小 x 坐标min(0, 11, 2000, 2020) - 2020最大 x 坐标max(0, 11, 2000, 2020) 2020最小 y 坐标min(0, 14, 11, 2000) - 2020最大 y 坐标max(0, 14, 11, 2000) 2020计算可得 x 范围大约为[-2020, 4040]y 范围类似。为了保险我们可以设置得稍微大一点例如[-2100, 4100]。这个矩形内的点总数大约是(410021001)^2 ≈ 6201^2 ≈ 38.4 million。虽然也有几千万个点但每个点的判断是O(1)的简单计算远比BFS中动态的哈希查找和队列操作要快得多。遍历与判定对于矩形区域内的每一个整数坐标(i, j)计算其到四个源点的曼哈顿距离d1 abs(i-0) abs(j-0)d2 abs(i-2020) abs(j-11)d3 abs(i-11) abs(j-14)d4 abs(i-2000) abs(j-2000)取这四个距离中的最小值min_dist。 如果min_dist 2020则该点在2020时刻内能被扩散到计数器ans加一。输出结果遍历结束后ans即为所求。3.2 C代码实现与关键技巧#include iostream #include cmath // 用于abs函数实际上用cstdlib的也可以但更常用cmath using namespace std; int main() { // 四个源点坐标 int sources[4][2] {{0, 0}, {2020, 11}, {11, 14}, {2000, 2000}}; int step 2020; // 计算遍历的边界稍微扩大范围确保覆盖 int min_x 0, max_x 0, min_y 0, max_y 0; for (int i 0; i 4; i) { min_x min(min_x, sources[i][0]); max_x max(max_x, sources[i][0]); min_y min(min_y, sources[i][1]); max_y max(max_y, sources[i][1]); } // 向四周扩展 step 的距离 min_x - step; max_x step; min_y - step; max_y step; // 为了更保险可以再额外扩大一些这里额外5 min_x - 5; max_x 5; min_y - 5; max_y 5; long long ans 0; // 结果可能很大用long long // 遍历矩形区域内的每一个点 for (int x min_x; x max_x; x) { for (int y min_y; y max_y; y) { int min_dist 1e9; // 初始化为一个很大的数 // 计算到四个源点的最小曼哈顿距离 for (int k 0; k 4; k) { int dist abs(x - sources[k][0]) abs(y - sources[k][1]); if (dist min_dist) { min_dist dist; } // 一个小优化如果发现距离已经小于等于step可以提前结束内层k循环 if (min_dist step) { // 这里不能直接break因为我们需要确保min_dist是正确的但可以快速判断成功 // 更稳妥的方式是继续计算但本题数据量下这个优化效果不明显。 } } // 如果最小距离在步数范围内则被覆盖 if (min_dist step) { ans; } } } cout ans endl; return 0; }关键技巧与解释边界计算代码中先找出源点的最小最大坐标再加减step这是一种通用且安全的做法。额外加减5是为了避免在边界条件上因整数计算可能出现的舍入问题属于一种“防御性编程”。数据类型答案ans使用long long。因为总点数可能超过int的范围约21亿。虽然本题最终答案在int范围内但养成好习惯很重要。循环优化在内层k循环中有一个被注释掉的优化。如果当前点到某个源点的距离已经 step那么它肯定是被覆盖的后续源点的距离计算可以跳过。这可以将最内层循环的平均次数降低到小于4。对于3800万次迭代这个优化能节省可观的时间。复杂度时间复杂度为O(R * C * 4)其中R和C是遍历矩形的行数和列数大约为6000量级所以总操作数约为6000*6000*4 ≈ 1.44亿。这在现代CPU上使用简单的整数运算是可以在1-2秒内完成的完全满足比赛要求。3.3 算法正确性证明与思维延伸为什么这个方法是正确的因为它和原始的BFS模拟是等价的。BFS模拟是从源点“主动”向外扩散记录被访问的节点。距离判定法是从平面“被动”地检查每个节点看它能否被某个源点在限定步数内“触及”。根据曼哈顿距离的定义一个点(x,y)能在t步内被源点(sx,sy)扩散到当且仅当|x-sx||y-sy| t。而BFS的过程恰恰就是逐步覆盖满足这个不等式的所有点的过程。这种从“过程模拟”到“状态判定”的思维转换在算法竞赛中非常常见。例如判断一个点是否在某个图形内我们不必模拟图形的生长过程而是直接用数学关系式判断。这道题就是一个绝佳的范例。4. 性能优化与边界探讨4.1 进一步优化减少遍历范围上面的遍历范围[-2100, 4100]是保守估计。实际上我们可以更精确地确定边界。对于一个源点(sx, sy)它能覆盖的点的x坐标范围是[sx - step, sx step]。那么四个源点覆盖范围的x轴并集就是min_x min(0-2020, 2020-2020, 11-2020, 2000-2020) min(-2020, 0, -2009, -20) -2020max_x max(02020, 20202020, 112020, 20002020) max(2020, 4040, 2031, 4020) 4040y轴同理。所以精确的遍历范围是x ∈ [-2020, 4040],y ∈ [-2020, 4020]读者可自行计算y的边界。这样遍历的点数从~6201^2减少到~6061*6041大约3660万个点减少了约15%的计算量。4.2 并行计算与向量化思考虽然比赛环境通常只使用单线程但思考优化方向是有益的。这个问题是“令人愉悦的并行”Embarrassingly Parallel。每个点(x, y)的判断完全不依赖于其他点。因此理论上可以很容易地将矩形区域划分成多个块用多个线程并行计算最后合并结果。这在CPU多核普及的今天是性能优化的标准思路之一。此外在循环计算曼哈顿距离时编译器通常会自动进行一定的向量化优化。我们也可以考虑使用SIMD指令集进行手动优化但这对算法竞赛来说属于“超纲”内容不过在实际工程应用中值得考虑。4.3 内存与缓存友好性我们的算法是O(1)额外空间只用了几个标量变量极其节省内存。遍历顺序是先行后列x在外y在内这在内存访问上是连续的如果我们将二维坐标想象成一个大数组有利于CPU缓存预取从而提升速度。这也是编写高效循环的一个小细节。5. 常见错误与调试心得5.1 典型错误清单使用BFS导致超时/超内存这是最常见的错误。没有进行规模估算直接上手写BFS结果程序运行缓慢甚至崩溃。边界计算错误在确定遍历矩形时少算了或者多算了边界。例如只用了源点的最小最大坐标没有加上step或者错误地认为遍历范围是[-step, max_coordstep]。整数溢出ans使用int类型当结果很大时溢出导致输出负数或错误结果。曼哈顿距离计算错误错误地使用了欧式距离公式sqrt((x1-x2)^2 (y1-y2)^2)或者忘记了取绝对值。判断条件错误错误地写成了min_dist step忽略了在tstep时刻恰好被扩散到的点。题目要求是“经过2020个单位时间后”意思是时间从0到2020包含第2020时刻。因此距离 step是正确的。循环变量类型在计算边界时如果step和坐标值都很大min_x等变量可能为负数如果使用了无符号整数unsigned int会导致下溢产生巨大正数使循环无法正常进行。5.2 调试与验证策略对于此类问题调试不能只靠眼睛看最终答案。可以采用以下策略小数据验证将step改为一个很小的数如2或3分别用BFS模拟和距离判定法计算。手动绘制网格标记源点模拟扩散过程核对两种方法的结果是否一致。这是验证算法逻辑正确性的黄金标准。输出中间结果对于小规模step可以输出被覆盖的点的坐标集合直观对比。性能预估在编写完整算法前先估算遍历的点数矩形面积和核心操作次数。如果估算值在亿级别且操作简单则算法可行如果估算值在十亿级别或涉及复杂操作则需要重新思考。利用对称性测试如果题目中源点是对称的例如本题不是那么结果可能具有对称性可以用来辅助判断。5.3 从这道题延伸的学习建议这道“扩散”题是一道非常好的教学题它考察的远不止是编码。复杂度意识看到2020这样的步数必须第一时间警惕O(N)或O(N^2)的模拟。要养成根据数据范围反推算法的习惯。模型转化能力能否将动态的“过程模拟”转化为静态的“条件判断”是区分普通选手和优秀选手的关键。这需要扎实的数学基础和灵活的思维。工具选择BFS/DFS是工具曼哈顿距离也是工具。在正确的场景选择最高效的工具就是算法能力。防御性编程使用long long仔细处理边界进行适当的范围放宽这些细节在赛场上能避免很多莫名其妙的失分。我个人在训练学生时经常用这道题举例。它就像一面镜子清晰地照出了解题者思维的不同层次第一层是直接模拟第二层是意识到模拟不可行第三层是转化为距离判定第四层还能思考更优的数学方法。即使最终只做到第三层也足以在比赛中拿到满分而这背后的思维跃迁过程才是练习算法题最宝贵的收获。编程竞赛赛的不仅是代码更是思路。

相关新闻

DM删除表空间:数据库存储管理的关键操作指南

DM删除表空间:数据库存储管理的关键操作指南

2026/8/28 4:48:47

一、表空间基础概念与删除必要性 1.1 什么是DM数据库表空间 DM数据库表空间是数据库存储逻辑结构的基本单位,用于存储数据库对象,如表、索引等。表空间由数据文件组成,这些文件在物理磁盘上存储数据,而在逻辑上由表空间进行组织和…

数学建模国赛四大题型解析:从优化预测到机理分析,Python实战指南

数学建模国赛四大题型解析:从优化预测到机理分析,Python实战指南

2026/8/28 4:48:46

1. 从“小白”到“破题”:国赛赛题类型深度解析与应对策略刚接触数学建模国赛的朋友,拿到赛题的第一反应往往是“这题在问什么?”和“我该从哪里下手?”。这种感觉非常正常,尤其是面对全国大学生数学建模竞赛&#xff…

头歌实践教学平台:数据科学与大数据技术导论(十五)

头歌实践教学平台:数据科学与大数据技术导论(十五)

2026/8/28 4:48:46

十五、数据科学导论——数学基础之矩阵第1关:什么是矩阵?任务描述 本关任务:使用列表创建一个 20 行 20 列的矩阵。相关知识 在线性代数中,由 m n 个数 aij 排成的 m 行 n 列的数表称为 m 行 n 列的矩阵,简称 m n 矩…

小米玄戒三芯齐发@ACP#端侧 AI 规模化落地,YLB3116 轻量化存储桥接在 AI 服务中的实践机会

小米玄戒三芯齐发@ACP#端侧 AI 规模化落地,YLB3116 轻量化存储桥接在 AI 服务中的实践机会

2026/8/28 6:18:51

本文面向硬件工程师、AI 整机方案开发者、嵌入式研发人员,结合小米玄戒 O3/O100/D100 三芯发布,剖析轻量化端侧 AI 整机 RAG 知识库、数据集存储的工程痛点,对比 YLB3116 与 YLB3118 产品定位差异,解析国产 PCIe 转 SATA 主控 YLB…

基于Qt与C++的扫雷游戏开发:课程设计实战与高分指南

基于Qt与C++的扫雷游戏开发:课程设计实战与高分指南

2026/8/28 6:18:51

简介:面向对象编程(OOP)是软件工程的核心范式,通过封装、继承和多态三大特性,将数据与操作数据的方法组织成类,从而构建出模块化、可复用、易维护的代码结构。其原理在于模拟现实世界,将复杂系统…

蓝桥杯省赛复盘:从“砍竹子”到“扫雷”的算法思维与实战技巧

蓝桥杯省赛复盘:从“砍竹子”到“扫雷”的算法思维与实战技巧

2026/8/28 6:18:51

1. 从一次“翻车”经历聊起:为什么我们要复盘2022年蓝桥杯省赛?去年省赛结束后,我带的几个学生从考场出来,脸上表情各异。有个平时刷题挺猛的小伙子,出来第一句话是:“老师,那个‘砍竹子’的题&…

27B级大模型量化实测:Q4_K_M与Q8_0的精度和显存对决

27B级大模型量化实测:Q4_K_M与Q8_0的精度和显存对决

2026/8/28 6:18:51

在本地部署 27B 级大模型时,最纠结的往往不是选哪张显卡,而是到底该用哪种量化精度。Q4 显存友好但担心效果缩水,Q8 精度更高但体积和显存压力也跟着上来,网上相关讨论一抓一大把,真正做成对照测试并给出结论的却不多。…

从零构建LLM:打通训练与推理全流程的工程实践

从零构建LLM:打通训练与推理全流程的工程实践

2026/8/28 6:18:51

很多人学深度学习,前半段是“舒服”的。卷积、循环网络、注意力机制,每章讲一个模块,跟着代码敲一遍,跑个小案例,能出一个结果,就觉得自己懂了。等课程进入后半段,尤其是类似“从零构建 LLM”的…

利用HDX-MS鉴定羟基马桑毒素与其靶点Tutin的结合位点

利用HDX-MS鉴定羟基马桑毒素与其靶点Tutin的结合位点

2026/8/28 6:08:51

药物毒性是药物研发面临的重要问题之一,科学技术的发展赋予毒理学研究更多先进的研究工具和手段,实现了从整体水平向细胞和分子水平的飞跃,各种组学技术的发展使得对毒性药物的直接作用靶点的检测更加方便。癫痫是一种反复性突然发作的脑功能…

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

2026/8/27 11:10:02

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

2026/8/27 7:25:23

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

2026/8/26 17:50:58

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

基于Claude Code的开源AI求职框架:从职位搜索到Offer的全自动化闭环

基于Claude Code的开源AI求职框架:从职位搜索到Offer的全自动化闭环

2026/8/28 0:08:32

当AI助手能够独立完成从职位匹配、简历定制到面试准备的全链路求职流程时,求职不再是一场信息战,而是一场工程化战役。框架概述:本地运行的AI求职引擎这是一个构建在Claude Code之上的开源AI求职框架,核心理念是"在工作者的机…

Godot 4 仿 agar.io:相机缩放被 max_zoom 卡死,窗口越大球越小的根因与修复

Godot 4 仿 agar.io:相机缩放被 max_zoom 卡死,窗口越大球越小的根因与修复

2026/8/28 0:08:32

1. 问题现象 在 Godot 4 仿 agar.io 的 2D 项目中,相机缩放设计为「由球组整体尺寸决定」,世界可见高度恒定,窗口只作为视口裁剪。默认小窗口 1280x720 时相机高度正常;但窗口最大化到 2940x1912 后,视角被明显拉远、…

从软件测试大赛到实战:Java+Selenium自动化测试进阶指南

从软件测试大赛到实战:Java+Selenium自动化测试进阶指南

2026/8/28 0:08:32

1. 缘起:从校园到赛场,我的软件测试之路几年前,我还是一个在校园里对着Java课本和“Hello World”程序挠头的普通学生。软件测试对我来说,只是一个在开发流程末尾、用鼠标点点按钮的模糊概念。直到我偶然在学校的公告栏上看到了“…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/22 2:02:26

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/26 18:07:30

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/26 17:57:52

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…