前言
在算法竞赛和编程中,对拍(Diff Testing)是一种高效验证代码正确性的方法。它通过对比暴力解法(Brute Force)和优化解法(Optimized Solution)的输出,快速发现逻辑错误。本文将提供完整的C++对拍代码,并逐步讲解其实现原理,帮助你轻松应用到自己的项目中。
对拍的实现
- 你想要测的方法a
- 实现复杂度不好但是正确的暴力解法b
- 实现一个随机样本产生器(长度随机,值也随机)
- 把方法a和方法b跑相同的输入样本,看看得到的结果是否一样
- 如果有一个随机样本使得方法a和方法b的结果不一致,说明存在问题,需要进一步分析
- 当样本数量很多时对比依然正确,可以确定方法a(最优解)已经正确
对拍的基本组成
一个完整的对拍系统需要以下部分:
暴力解法程序(baoli.cpp):保证正确但效率较低,用于生成标准答案。
待测优化程序(zhengjie.cpp):需要验证的高效算法。
随机数据生成器(makedata.cpp):生成合法输入数据。
对拍脚本(duipai.cpp):自动化运行并对比结果。
使用方法
直接运行duipai.cpp即可。它会自动运行随机数据生成器makedata.cpp,生成合法输入数据,运行暴力解法程序baoli.cpp和优化解法程序zhengjie.cpp。对比结果,验证输出结果是否一致。如果结果不一致,则输出错误信息,并输出测试数据和结果。
C++代码实现-以排序为例
1. 暴力解法程序(baoli.cpp)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> nums(n + 1);
for (int i = 1; i <= n; i++) {
cin >> nums[i];
}
for (int i = 1; i <= n; i++) { // 冒泡排序
for (int j = i + 1; j <= n; j++) {
if (nums[i] > nums[j]) {
swap(nums[i], nums[j]);
}
}
}
for (int i = 1; i <= n; i++) {
cout << nums[i] << " ";
}
return 0;
}
作用:提供一个绝对正确的解法(即使时间复杂度较高),用于验证优化程序的正确性。
2. 待测优化程序(zhengjie.cpp)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> nums(n + 1);
for (int i = 1; i <= n; i++) {
cin >> nums[i];
}
sort(nums.begin() + 1, nums.begin() + n + 1); // 快速排序
for (int i = 1; i <= n; i++) {
cout << nums[i] << " ";
}
return 0;
}
作用:提供一个需要验证的高效算法,用于对比暴力解法的正确性。
3. 随机数据生成器(makedata.cpp)
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <bits/stdc++.h>
using namespace std;
int main() {
std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count()); // 随机数生成器
int n = rng() % 100 + 1; // 数组的长度范围为[1, 100]
int v = 1000; // 数组中的数据范围为[0, v)
cout << n << endl;
for (int i = 1; i <= n; i++) {
cout << rng() % v << " "; // 随机生成[0, v)的整数
}
return 0;
}
作用:生成随机输入数据,确保测试覆盖各种边界情况(如负数、0、最大值等)。
4. 对拍主程序(duipai.cpp)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <bits/stdc++.h>
using namespace std;
int main() {
system("g++ -std=c++11 baoli.cpp -o baoli.exe");
system("g++ -std=c++11 zhengjie.cpp -o zhengjie.exe");
system("g++ -std=c++11 makedata.cpp -o makedata.exe");
while (1) {
system("makedata.exe > makedata.txt");
system("baoli.exe < makedata.txt > baoli.txt");
system("zhengjie.exe < makedata.txt > zhengjie.txt");
if (system("fc baoli.txt zhengjie.txt")) {
cout << "Wrong Answer" << endl;
system("type makedata.txt");
system("type baoli.txt");
system("type zhengjie.txt");
break;
} else {
cout << "Accepted" << endl;
}
}
return 0;
}
作用:自动运行暴力解法和优化解法,对比结果,输出结果是否一致。
总结
对拍是一种高效验证代码正确性的方法,通过对比暴力解法和优化解法的输出,快速发现逻辑错误。本文介绍了对拍的基本组成,并给出了C++对拍代码的实现。希望能帮助你轻松应用到自己的项目中。