ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

蓝桥杯备赛第一周:Dijkstra算法优化与高频考点实战总结

2026/9/15 0:07:11 拓冰建站 浏览量
蓝桥杯备赛第一周:Dijkstra算法优化与高频考点实战总结 蓝桥杯备赛学习总结第1周1. 起跑前先想清楚这一周我到底在备什么说实话决定报名蓝桥杯的时候我脑子里对它的认知基本还停留在“一个编程比赛”这个模糊的层面上。真正开始备赛是上周一的事情。当时我给自己定的目标是用一周时间摸清楚蓝桥杯到底考什么、难度在哪、我的水平跟它之间的距离有多大顺便把刷题环境、真题资源、学习路线全部理顺。现在回看这一周踩过的坑不少但也有几条路走通了趁热记录下来既是给自己的备赛过程留个底也能给同样刚开始准备的朋友一些参考。先说结论蓝桥杯不是一个靠“突击刷题”就能拿奖的比赛但它也远没有到需要你拥有竞赛级天赋才能参与的程度。它的核心特征是“广而不深”——考点覆盖面很宽但单个知识点的考察难度通常不会拉到很高。这意味着备赛策略跟打ACM完全不一样你不一定需要把每一类算法都学得炉火纯青但你需要做到“见过的题型都会会做的题型不丢分”。那第一周的重点就很清晰了先把比赛本身研究透再动手刷题。我见过太多人一上来就闷头刷题刷了一周连比赛有几道题、怎么计分都没搞清楚——这不是备赛这是自我感动。我选的组别是Java B组原因很现实我日常开发主力语言是Java不用额外花时间重新熟悉语法。但我身边也有不少同学在纠结选Java、Python还是C。我的建议是除非你的C底子非常扎实否则不要因为“C拿奖容易”这种说法去临时转语言。蓝桥杯的奖是跟你的编程熟练度强相关的语言切换的成本远比你想象中高。Python组和Java组在B组的分数线差异存在但不值得你为此付出额外两个月的语法磨合期。第一周我还做了一件非常重要的事把往年真题的题面全部翻了一遍。注意不是做题是看题面。从省赛到国赛从第一届到最近一届我把它们的题目类型、考察知识点结构全部整理成了表格。这么做的好处是你能在很短的时间内建立起对比赛出题风格的直觉——哪个知识点出现频率最高、什么题型最容易作为压轴题、哪类题看起来很复杂但实际上有固定套路。这个直觉会在你后续刷题时帮你排优先级非常有用。2. 真题摸底先被“出差”这道题上了一课摸底真题的时候我看到一道题叫“[蓝桥杯 2022 国 B] 出差”当时第一反应是“国赛题那应该很难吧”于是带着敬畏心点开。读完题面我发现这道题本质上是一道图论最短路问题场景设定是城市之间出差需要计算最短时间但中间加了点干扰信息——比如某些城市有额外的隔离时间当时看到“隔离”这个字眼我脑子里闪过一丝不好的联想赶紧确认了一下这只是题目场景里的一个业务规则跟现实无关可以放心讨论算法本身。题目的核心模型是这样的城市作为图的节点城市之间的交通线路作为边每条边有权重交通时间同时每个城市还有一个额外的停留时间。从起点出发到终点经过某个城市就要加上这个城市的停留时间。本质上就是在Dijkstra算法的基础上把节点权重也纳入计算。我试着用朴素Dijkstra写了一遍提交之后发现超时了。这时候我意识到一个问题——国赛题跟省赛题的关键区别可能不在算法思想上而在数据规模和优化要求上。这道题需要用优先队列优化的Dijkstra才能过时间复杂度才能压进要求。这个发现对我来说很重要蓝桥杯的考察点并不完全是“你会不会这个算法”而是“你会不会在实际限制条件下应用这个算法”。下面是我第一次写的朴素版本完全能跑但大数据量下直接超时// 朴素Dijkstra小数据量可过大数据量超时 public static int dijkstra(int n, int[][] graph, int[] stayTime, int start, int end) { int[] dist new int[n 1]; boolean[] visited new boolean[n 1]; Arrays.fill(dist, Integer.MAX_VALUE); dist[start] 0; for (int i 0; i n; i) { int u -1, minDist Integer.MAX_VALUE; for (int j 1; j n; j) { if (!visited[j] dist[j] minDist) { minDist dist[j]; u j; } } if (u -1) break; visited[u] true; for (int v 1; v n; v) { if (!visited[v] graph[u][v] ! Integer.MAX_VALUE) { int cost graph[u][v] stayTime[v]; if (dist[u] cost dist[v]) { dist[v] dist[u] cost; } } } } return dist[end]; }问题出在最内层找最小节点的循环是O(n)的整体复杂度O(n^2)。当n达到几千甚至上万时这个复杂度就是灾难。优化后的版本用PriorityQueue维护当前可达节点每次取距离最小的节点复杂度降到O((nm)logn)// 优先队列优化Dijkstra public static long dijkstraOptimized(int n, Listint[][] adj, int[] stayTime, int start, int end) { long[] dist new long[n 1]; Arrays.fill(dist, Long.MAX_VALUE); dist[start] 0; PriorityQueuelong[] pq new PriorityQueue((a, b) - Long.compare(a[1], b[1])); pq.offer(new long[]{start, 0}); while (!pq.isEmpty()) { long[] cur pq.poll(); int u (int) cur[0]; long d cur[1]; if (d dist[u]) continue; if (u end) break; for (int[] edge : adj[u]) { int v edge[0], w edge[1]; long nd d w stayTime[v]; if (nd dist[v]) { dist[v] nd; pq.offer(new long[]{v, nd}); } } } return dist[end]; }这个优化看起来不难但是如果你没有提前了解过“蓝桥杯的算法题数据范围可以到多大”你是不会有意识去做这种优化的。这也是我第一周最大的收获之一备赛不只是学算法还要学“在限制条件下选对实现方式”。排查这道题的时候我还发现一个容易错的细节起点城市要不要算停留时间题目里说的规则是出发时不加停留时间到达目标城市时才需要加。如果你没仔细读题把起点的停留时间也算进去小数据可能没感觉一旦数据量大了很多用例会因此WA。这种“题目里的一句话决定成败”的情况在蓝桥杯真题里非常普遍。3. 备赛资料与工具链少走弯路的选型心得第一周除了摸底真题我还花了不少时间搭建自己的备赛环境。这一步看似不起眼实际影响很大——环境不顺手刷题效率会直线下降。先说说OJ平台的选择。蓝桥杯官方有练习系统里面包含历届真题从省赛到国赛这是最权威的资源没有之一。市面上也有一些第三方OJ收录了蓝桥杯题目但题目描述和输入输出格式偶尔会有出入我建议以官方为准。我自己的习惯是官方系统刷真题其他平台拿来练特定算法专题。然后是本地开发环境。如果你选的是Java组我强烈建议你从第一天开始就用IDEA Maven工程来刷题而不是在在线OJ的网页编辑器里直接写。原因不只是IDEA的补全和调试功能更强大更重要的是蓝桥杯正式比赛用的就是类似IDEA的IDE环境具体是Eclipse还是IDEA每年可能有差异提前适应在IDE里写代码、跑用例、调试的感觉能避免比赛时因为环境陌生而手忙脚乱。Python组的话PyCharm或者VS Code都行看个人习惯C组Visual Studio或者CLion也都可以。输入输出这块有个细节必须单独说蓝桥杯的评测输入是标准输入输出也是标准输出不需要文件读写。但题目里的输入格式往往有多行、多组测试用例很多人第一次刷题会卡在“怎么读多组数据”上。Java组的解法是使用BufferedReader配合StringTokenizer来快速读取而不是Scanner。Scanner在数据量大的时候性能不够可能比别人慢一倍都不止。我第一周就统一封装了一个FastReader工具类后面所有题都用它来读输入// 快速输入模板蓝桥杯Java组必备 static class FastReader { BufferedReader br; StringTokenizer st; public FastReader() { br new BufferedReader(new InputStreamReader(System.in)); } String next() { while (st null || !st.hasMoreTokens()) { try { st new StringTokenizer(br.readLine()); } catch (IOException e) { e.printStackTrace(); } } return st.nextToken(); } int nextInt() { return Integer.parseInt(next()); } long nextLong() { return Long.parseLong(next()); } double nextDouble() { return Double.parseDouble(next()); } }这个模板我从第一周用到现在所有真题的输入读取都能覆盖。你别小看这个读写层面的准备在蓝桥杯这种“大家都会做就看谁快谁稳”的比赛中基础代码的可靠性和速度就是隐形的分数。另外我还整理了一个“蓝桥杯Java组考点清单”的文档按数据结构、算法、数学、动态规划、图论、字符串、贪心、搜索等分类把近五年的省赛和国赛真题都标进去。这样做的价值在于我能直观看到哪些知识点出现频率高。以Java B组省赛为例动态规划和贪心几乎是每年必考图论和搜索交替出现字符串处理大概率会有一道。有了这个清单我后续的学习顺序就有了依据——优先搞高频考点冷门知识点放到后面再说。最后想说一下题量的规划。第一周我给自己定的量是每天3-5道题其中至少一道是真题。一开始不要追求一天刷十道因为每道题做完之后你还需要留出时间总结为什么这么解有没有更优的做法我的代码在大数据下会不会超时如果能把这些问题想明白一天三道题的效果远好于囫囵吞枣做十道。第一周结束我总共完成了约20道题的练习其中有5道是历年真题2道是国赛题包括前面说的那道“出差”这个进度我个人是比较满意的。4. 每天的时间分配与刷题节奏第一周实际执行下来的复盘很多人的备赛计划失败不是因为不够努力而是因为计划本身反人性。我第一周的第一版计划是“每天早上6点起床刷题两小时”执行了两天就崩了——不是起不来而是睡眠不足导致白天状态极差刷题效率反而下降。于是我调整了策略把刷题时间跟自己的精力曲线对齐。我把每天分成三个时间段——早上60分钟专门做算法理论学习下午或者晚上精力最集中的时候用来刷真题睡前再用30分钟复盘当天做的题和整理的错题。我执行的每日时间分配大概是这样的时间任务目标早上30分钟复习前一天错题 30分钟学习一个新算法知识点巩固旧知接触新知下午/晚上90-120分钟集中刷题2-3道保证有效题量睡前30分钟复盘 整理笔记记录思路和细节碎片时间看真题题面分析考点培养审题直觉这个节奏执行下来最大的感受是备赛跟健身一样最重要的不是某一天练得有多狠而是能不能持续。一周7天我实际执行了6天中间有1天因为学校课程太忙确实没刷题但我也没有因此焦虑。备赛是长跑不是冲刺。在这个过程中我还总结出一个很重要的方法每道题做完之后在代码文件头部用注释写清楚三件事——题目考点、我的初始思路、卡住的地方。这样过两周回头复习时你不需要重新看一遍完整代码只需要看这三行注释就能快速回忆起来。下面是我给一道动态规划题写的注释示例// 考点01背包变种每个物品可以选择放入或不放入但容量和价值范围不同 // 初始思路直觉是二维DPdp[i][j]表示前i个物品容量为j时的最大价值 // 卡点数据范围到了10^5二维数组直接MLE需要优化为一维滚动数组 // 解法先按价值排序再用一维dp倒序遍历或者用贪心优先队列处理这个方法我强烈推荐尤其适合需要在几个月内保持高强度备赛的人。你的笔记系统不需要多精美但一定要能让你快速回忆起当时的思考过程。时间分配之外我还想聊聊关于“要不要参加模拟赛”的问题。第一周我就在蓝桥杯官网上留意到了模拟赛的入口但当时没敢报——因为我觉得自己基础还不够。一周之后回头看我反而觉得第一次模拟赛越早参加越好哪怕成绩很难看也没关系。原因是模拟赛能让你提前经历“限时做题”的紧张感。平时刷题你可以想一个小时但比赛里一道题就那么多时间心态完全不一样。早一点体验这种压力后面正式比赛的时候就不会那么慌。我第二周的计划里就报了一场模拟赛到时候再来分享感受。5. 第一周踩过的坑与避坑清单最后分享几个第一周实打实踩过的坑都是泪换来的经验。第一个坑是“只刷题不总结”。前面我说过一天刷三道题但一定要复盘这不是空话。第一周前两天我试过一天刷六道题当时觉得特别充实结果周末回看那些题等于白做——代码写着写着就忘了当初为什么这么设计下次遇到同类题照样卡住。后来我强制自己每天只做2-3道但每道题写完后必须花20-30分钟写注释、复盘、总结。这个转变直接让我的做题质量提升了一个档次。第二个坑是“过度纠结一道题”。刚开始刷真题时遇到一道难题我死磕了两个小时还没想出来后来又花了一个小时看题解才看懂。整个过程耗时三个小时但并不值得——因为那道题的知识点超出了当前阶段的范围而我却用它挤占了本应完成的基础巩固时间。我现在遇到难题的标准流程是先想15-20分钟如果完全没有思路直接看题解理解后独立重写一遍然后在笔记里标记“待二刷”等知识储备更充足了再回来做。这样既不浪费时间也能保证见过难题、知道它考什么。第三个坑是“盲目追求算法新奇度”。蓝桥杯很多题目的最优解确实需要比较高级的数据结构比如线段树、树状数组、并查集等等但省赛范围内大部分题用基础算法加适当优化就能解出来。第一周我有一次做题想着用线段树去解一道区间查询题写了一大半发现其实用前缀和加一次遍历就能过。那一刻我突然意识到在蓝桥杯里能拿分的算法就是好算法而不是看起来高深的算法。先把基础打牢再去追求高级数据结构这个顺序不能反。第四个坑是关于读题的。我发现蓝桥杯的题面有一个特点——它喜欢用故事场景来包装算法问题比如“出差”“货物调度”“魔法森林”之类。第一周我做一道模拟题时被题面里的故事带着走了忽略了真正约束条件的细节导致漏判了一种边界情况。后来我养成了一个习惯读题时直接把数据范围、输入格式、输出要求里涉及的关键词圈出来特别是“整数”“非负”“可能为0”“保证答案存在”这类限定词这些往往就是出题人埋下的坑所在。第五个坑跟代码提交相关。第一次在官方系统提交代码时我的类名写成了Main1结果直接编译错误。蓝桥杯官方要求提交代码时主类的类名必须是MainJava组C组的main函数返回类型必须是intPython组则要注意不要写交互式的输入输出。这些看起来是小问题但真到比赛时一次编译错误可能就让你丢掉整道题的分数。建议你第一次刷题提交前就养成“类名统一写Main”的习惯免得后面改来改去。6. 下一周的备赛方向从“摸清底细”转向“系统补漏”第一周的目标是“摸清底细”这个目标算是完成了。第二周开始备赛节奏就要从“认识比赛”切换到“系统补漏”了。我给自己定的第二周计划主要有三件事。第一件事是把动态规划这个高频考点系统过一遍从最基础的背包问题开始逐步过渡到区间DP和树形DP每类至少做3道真题或真题变体来巩固。第二件事是坚持每天二刷一道第一周做过的题——不看任何笔记完全靠记忆和肌肉记忆写出来写不出来的地方就是我的薄弱点需要重点标记。第三件事是参加第一场模拟赛不求分数只求体验完整的比赛流程和时间压力。另外我还打算开始建立自己的“模板库”。蓝桥杯的很多算法其实都有相对固定的模板代码比如快速幂模板、并查集模板、前缀和与差分模板、Dijkstra模板等等。第一周我已经写了快速输入模板第二周要把这些常用算法模板也整理出来。但有一点要注意模板不能只是背而是要在理解的基础上手写出来因为比赛时你不可能记起一个完全没理解过的代码片段。第一周的备赛总结就写到这里。回头看看这一周最大的收获不是做了多少道题而是建立起了“真题驱动学习”的备赛框架——先知道考什么再有针对性地补什么而不是漫无目的地刷题。这个框架在后续几个月里应该会持续发挥作用。下一周比赛季的模拟赛成绩出来之后我再来记录新的感受和经验。