| Resources | |||||
|---|---|---|---|---|---|
| KACTL | ICPC 比赛中可以尝试的排错方法 | ||||
| Errichto | |||||
本模块以上述资源为基础,并选取了与 USACO 最相关的内容。
提交前
- 代码应当具有可读性,至少要让你自己能够读懂。
- 可以参考添加题解模块中的代码 风格建议。
答案错误(或运行错误)
输出格式是否正确?
- 提交前是否删除了调试输出?
是否处理了所有边界情况(例如 )和特殊情况?
对含有多组独立测试数据的题目(例如此题), 是否在每组数据之间清空了所有数据结构?
- 有时程序只会在较大的测试数据之后紧跟较小数据时出错。
是否正确理解了题意?重新完整阅读一遍题面。
再读一遍代码。
- 是否混淆了 与 、 与 等变量?
是否存在_未定义行为_?它可能导致本地与在线评测结果不同,例如样例在本地 通过,提交到 USACO 却失败。尝试在多个环境中运行代码,例如 USACO Guide IDE 和 Codeforces 自定义测试, 观察结果是否始终相同。常见的未定义行为包括:
C++:未初始化的变量;
C++:非
void函数没有返回值;C++:数组越界;
- 可以按此处所述使用
::at;
C++ / Java: 有符号整数溢出
- 若题目需要 64 位而非 32 位整数,USACO 通常会给出类似下面的提示,但很 容易被忽略:
请注意,本题涉及的整数较大,可能需要使用 64 位整数类型(例如 C/C++ 中的
long long)。C++:将一个 32 位整数移位 位。
C++ 使用检测选项
-fsanitize=address,undefined编译,有助于发现这些问题。添加断言后重新提交。
浮点数:
- 是否产生了
NaN,例如对负数开平方? - 尝试使用精度更高的类型,例如 C++ 中用
long double代替double。 - 输出精度是否正确?
算法本身是否真的正确?
- 用简单样例手动执行算法,或编写测试数据运行。
- 编写数据生成器,把程序输出与较简单的暴力解或标准解比较。
- 更多信息参见对拍。
运行错误
- 是否存在未定义行为(见上文)?
- 是否有可能失败的断言?
- 是否可能除以零,例如对零取模?
- 是否可能无限递归?
- 是否使用了已经失效的指针或迭代器?
- 是否占用了过多内存?
超出时间限制
- 是否可能存在死循环?
- 算法复杂度是多少?
- 提交前是否移除了调试输出,例如是否向标准错误流 输出了大量信息?
- 是否进行了不必要的数据复制?C++ 中可考虑按引用传参。
- C++ 中尝试用
array替代vector。
最后的办法
- 从头重写解答。
- 务必保留原代码的副本,因为新实现也可能引入更多错误。
在 USACO Guide Forum 发帖前
- 如果已经找到程序失败的小测试,并且知道正确输出为何成立,通常应当能自行 找出程序错误。
- 在代码中添加输出语句,与手动模拟的结果逐步比较。
- 按上文说明检查未定义行为。
- 如果还没有找到失败的小测试:
- 尝试下载官方测试数据,查看程序是否在其中的小数据上失败。
- 若仍不行,按上文方法生成一个能使程序失败的小测试。