为什么要留痕
本仓库不仅保存答案,也保存需求分析、算法设计、调试过程和运行结果。对训练而言,真正有价值的不是“某次 AC”,而是:
- 你如何发现错误
- 你如何修正错误
- 你如何证明程序确实稳定可用
如果没有测试记录和运行证据,很多“会做”只停留在感觉层面,无法复盘,也无法复用。
测试不是最后一步,而是贯穿整个解题过程
一个稳定的节奏通常是:
- 写出最小可运行版本后,立即跑题面样例。
- 样例通过后,补边界数据。
- 功能基本正确后,补异常数据和压力数据。
- 提交前保存最终运行结果、日志和关键截图。
这样做的好处是,错误会在更早阶段暴露,修正成本更低。
建议保存的内容
- 编译输出
- 标准输出与错误输出
- 耗时与返回码
- 关键截图
- 调试记录
- 最终报告 PDF
除此之外,建议再补两类材料:
- 自造测试数据:说明你不是只依赖题面样例
- 修复说明:记录“错误现象 -> 原因 -> 修正方式”
测试分层
题面样例测试
作用:
- 确认你理解了基本输入输出格式
- 验证最小实现能否跑通
不足:
- 样例通常覆盖不到所有边界
- 通过样例不等于程序正确
边界测试
重点覆盖:
- 最小数据规模
- 最大数据规模
- 全部相同、全部递增、全部递减
- 只有一个元素、只有一条路径、只有一个阶段
- 所有值都刚好卡在阈值附近
异常或脏数据测试
对数据清洗类和模拟类题尤其重要,例如 s1-jh-03-heritage-data-standard:
- 缺字段
- 字段顺序不一致
- 单位不统一
- 状态重复或无效
性能测试
重点问题:
- 数据量变大后是否超时
- 是否存在重复排序、重复扫描
- 日志输出是否过多影响速度
对于 s2-jh-01-route-supply、s4-jh-02-production-plan 这类调度题,这一步尤其必要。
日志应该记什么
日志的目标不是“越多越好”,而是让你快速定位错误。
建议记录:
- 当前读入的关键参数
- 每轮迭代的重要状态变化
- 异常触发条件
- 最终结果前的关键中间值
不建议记录:
- 每个细节变量的重复打印
- 大量无意义的“进入函数”“离开函数”
- 会淹没关键信息的大规模原始数组打印
如何区分正式输出和调试信息
原则很简单:
- 正式输出只面向评测系统
- 调试信息只面向开发者
实践中可以这样做:
- 使用单独日志文件
- 使用标准错误输出
- 使用可开关的调试标志
- 提交前关闭全部调试信息
证据链应该如何组织
在本仓库的 case 目录里,通常可以对应到如下材料:
01-requirements/:题目理解、约束拆解、验收标准02-solution/:代码、样例、算法说明03-execution/:运行日志、输出结果、截图04-debug/:调试记录和修复过程05-rationale/:结构化说明06-deliverables/:最终交付物
理想状态下,一道题的完整证据链应该能回答:
- 题目要求是什么
- 算法为何这么选
- 代码如何实现
- 中间遇到了什么问题
- 最终如何证明程序可运行
常见比赛场景中的测试重点
流程模拟类
如 s1-jh-02-heritage-simulation、s2-jh-03-propagation-sim:
- 多阶段状态是否正确传递
- 异常是否只触发一次还是会连锁触发
- 恢复机制是否改变后续状态
趋势分析类
如 s2-jh-02-livelihood-trend、s4-jh-03-promotion-forecast:
- 缺失月份或异常值是否处理
- 趋势标签边界是否正确
- 预测时是否误用了未来数据
调度规划类
如 s2-jh-01-route-supply、s4-jh-02-production-plan:
- 约束是否全部生效
- 可行解和最优解有没有混淆
- 在多方案并存时,输出是否满足题面要求的比较规则
常见错误与修正方式
错误 1:只测样例
问题:
- 样例通过,但一到边界数据就错
修正:
- 每道题至少补最小值、最大值、特殊结构值三类测试
错误 2:日志太多,反而看不见关键信息
问题:
- 整屏都是输出,却不知道异常发生在何处
修正:
- 只记录关键状态节点
- 给日志加阶段名或序号
错误 3:修好 bug 后没有保留原因
问题:
- 过两天再看,不知道为什么这么改
修正:
- 在
04-debug或笔记中记录 bug 根因与修复思路
错误 4:性能测试时仍然打开详细日志
问题:
- 误把日志 IO 当成算法性能
修正:
- 性能测试使用关闭日志的版本
- 单独记录算法时间和日志时间
一份可执行的调试记录模板
可以为每次问题记录以下字段:
| 字段 | 说明 |
|---|---|
| 问题编号 | 便于追踪 |
| 触发数据 | 哪组数据导致问题 |
| 错误现象 | 输出错误、超时、崩溃、格式错误 |
| 初步判断 | 可能是解析、逻辑、边界还是性能问题 |
| 修复动作 | 改了什么 |
| 验证结果 | 修复后重新跑哪些测试 |
训练建议
- 为任意一道 case 补 5 组自造测试数据。
- 至少记录一次“错误现象 -> 原因 -> 修复”的完整过程。
- 对模拟题做一次状态跟踪表,对调度题做一次约束检查表。
- 提交前用无调试输出版本重新运行全部关键测试。
最后的自检问题
- 是否只依赖样例,还是已经覆盖边界场景
- 是否保留了必要日志和运行证据
- 是否能说清每次 bug 的原因
- 是否把最终正确结果与调试输出分开
- 是否能让别人只看证据链就理解你的解题过程