1. 项目概述
作为一名算法竞赛爱好者,我最近在洛谷平台开启了为期30天的刷题挑战。今天要分享的是第六天的刷题实录,主要涉及动态规划、图论和贪心算法的经典题型。不同于前五天的基础训练,第六天的题目难度明显提升,更考验对算法本质的理解和灵活运用能力。
选择洛谷作为刷题平台有几个明显优势:题目分类清晰、测试用例全面、社区讨论活跃。特别是每道题目的题解区,经常能看到各路高手的不同解法,这对拓宽解题思路非常有帮助。我的刷题策略是每天固定3-5道中等难度题目,保证每道题都吃透原理,而不是单纯追求数量。
2. 刷题准备与环境配置
2.1 开发环境搭建
我使用的开发环境是VS Code + C++17标准,配合Competitive Companion插件实现一键抓题。这个组合的优势在于:
- 代码补全和错误检查功能完善
- 插件自动生成题目模板和测试用例
- 支持一键提交和结果反馈
配置要点包括:
- 安装MinGW-w64作为编译器
- 配置tasks.json实现编译运行快捷键
- 设置代码片段模板(如快速生成头文件)
注意:竞赛编程与工程开发不同,通常需要关闭同步流以提升IO速度。我的常用配置是:
ios::sync_with_stdio(false); cin.tie(nullptr);2.2 刷题方法论
经过前五天的实践,我总结出一套有效的刷题流程:
- 理解题意:至少读题3遍,用自己语言复述问题
- 确定算法:根据题目特征匹配算法类型(如看到"最优化"考虑DP)
- 手写测试:在纸上模拟小规模案例
- 代码实现:先写伪代码再填充细节
- 调试优化:针对特殊边界条件测试
特别重要的是建立错题本,记录每道错题的:
- 错误原因(逻辑/边界/复杂度)
- 正确解法思路
- 同类题目链接
3. 今日刷题实录
3.1 动态规划专题:P1048 采药
这道经典DP题实质是0-1背包问题的变种。药材对应物品,时间限制对应背包容量。我的解题过程:
- 状态定义:dp[i][j]表示前i株药材在j时间内的最大价值
- 转移方程:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-time[i]] + value[i]) - 空间优化:使用滚动数组将空间复杂度从O(NM)降到O(M)
踩坑记录:
- 初始化为-INF而不是0(允许时间不满)
- 第二层循环需要倒序遍历(防止重复计算)
- 药材编号从1开始更符合直觉
最终AC代码的关键部分:
vector<int> dp(T+1); for(int i=1; i<=M; ++i){ for(int j=T; j>=t[i]; --j){ dp[j] = max(dp[j], dp[j-t[i]] + v[i]); } }3.2 图论实战:P3371 单源最短路径
这道题要求实现Dijkstra算法,但有几点需要注意:
- 数据规模较大(n≤1e4),邻接表存储更优
- 需要处理重边情况
- 使用优先队列优化时间复杂度
我的实现步骤:
- 链式前向星建图
- 小根堆维护待处理节点
- 松弛操作时判断距离更新
性能优化技巧:
- 使用pair<int,int>时默认按first排序
- 提前判断if(dis[u]<d) continue节省时间
- 输入使用快速读入函数
实测对比:普通队列实现500ms,堆优化后仅120ms
3.3 贪心算法:P1223 排队接水
这道题展示了贪心算法的典型特征:局部最优导致全局最优。解题关键在于发现"短任务优先"的规律。
数学证明: 设两个任务时间分别为t1和t2,且t1<t2
- 顺序1→2:等待时间=t1 + (t1+t2)
- 顺序2→1:等待时间=t2 + (t2+t1) 显然第一种顺序更优
实现细节:
- 使用结构体数组保存原始序号
- 自定义排序函数按时间升序
- 计算前缀和得到总等待时间
易错点:
- 平均数计算要用double类型
- 输出格式要求保留两位小数
- 序号从1开始但数组从0存储
4. 调试技巧与性能分析
4.1 常见错误排查
在今天的刷题过程中遇到了几个典型错误:
段错误(Segmentation Fault)
- 原因:数组越界访问
- 解决方法:检查循环边界条件,使用.at()方法捕获异常
TLE(Time Limit Exceeded)
- 案例:Dijkstra未使用堆优化
- 优化方案:时间复杂度从O(V^2)降到O(ElogV)
WA(Wrong Answer)
- 调试方法:构造极端测试用例(如空输入、最大值边界)
4.2 性能分析工具
推荐使用洛谷自带的"测试点详情"功能,可以:
- 查看每个测试点的通过情况
- 对比时间/内存消耗
- 定位性能瓶颈
对于本地测试,我常用的方法:
g++ -O2 -std=c++17 -o test test.cpp time ./test < input.txt5. 算法学习资源推荐
经过六天的刷题,我发现这些资源特别有帮助:
书籍类
- 《算法竞赛入门经典》- 刘汝佳
- 《挑战程序设计竞赛》- 秋叶拓哉
在线资源
- OI Wiki(全面系统的算法百科)
- CP-Algorithms(英文版算法详解)
视频课程
- 洛谷官方算法课
- Codeforces教育频道
6. 明日刷题计划
基于今日的经验,明天计划:
- 巩固DP中的状态压缩技巧
- 学习图论中的最小生成树算法
- 尝试一道难度评级为「省选/NOI-」的题目
具体题目选择:
- P1433 吃奶酪(状压DP经典)
- P3366 【模板】最小生成树
- P1073 最优贸易(图论综合题)
刷题过程中我会特别注意:
- 复杂度的预先计算
- 状态转移的数学证明
- 边界条件的全面考虑
今天最大的收获是理解了贪心算法的证明方法——不是所有看似合理的贪心策略都正确,必须通过严格的数学证明或反例验证。比如在接水问题中,如果改为"先处理等待时间长的任务"就会得到错误结果。