- C++
对拍
- @ 2026-9-22 22:05:19
对拍是一种进行检验或调试的方法,通过对比两个程序的输出来检验程序的正确性。可以将自己程序的输出与其他程序的输出进行对比,从而判断自己的程序是否正确。 对拍过程要多次进行,因此需要通过批处理的方法来实现对拍的自动化。 具体而言,对拍需要一个 数据生成器 和两个要进行输出结果比对的程序。 每运行一次数据生成器都将生成的数据写入输入文件,通过重定向的方法使两个程序读入数据,并将输出写入指定文件,最后利用 Windows 下的 fc 命令比对文件(Linux 下为 diff 命令)来检验程序的正确性。如果发现程序出错,可以直接利用刚刚生成的数据进行调试。
想要实现对拍,所在题目文件夹下至少需要有4个代码文件,结构如下:
文件夹/
├── gen.cpp # 数据生成器 需要先编译生成可执行文件
├── baoli.cpp # 暴力解法 需要先编译生成可执行文件
├── youhua.cpp # 优化解法 需要先编译生成可执行文件
└── duipai.cpp # 对拍程序
windows 系统的可执行文件后缀名是 .exe ,linux系统的可执行文件没有后缀名。
数据生成器 gen.cpp
#include <iostream>
#include <random> //梅森旋转算法生成器
#include <ctime> //time(0), 获取时间戳,作为随机种子
using namespace std;
// 生成 [min, max] 范围内的随机整数
long long random_range(long long min, long long max) {
static mt19937_64 gen(time(0)); // 梅森旋转算法生成器, static 静态,只会执行一次,函数结束后不释放
uniform_int_distribution<long long> dis(min, max); // 均匀整数分布
return dis(gen);
}
int main() {
// 随机生成长度1-5的数组,不宜太大,太大了会难以分析问题
int n = random_range(1,5);
cout << n << endl;
for (int i = 0; i < n; i++) {
cout << random_range(-3e9, 3e9) << " ";
}
cout << endl;
return 0;
}
对拍程序 duipai.cpp
分两个版本
Linux 版本
#include <cstdio>
#include <cstdlib>
int main() {
// For Linux
// 对拍时不开文件输入输出
// 当然,这段程序也可以改写成批处理的形式
while (true) {
system("./gen > test.in"); // 数据生成器将生成数据写入输入文件
system("./baoli < test.in > a.out"); // 取暴力代码的输出
system("./youhua < test.in > b.out"); // 获取要提交的程序的输出
if (system("diff a.out b.out")) {
// 该行语句比对输入输出
// diff直接输出不同处
system("cat test.in"); //显示输入文件内容
return 0;
// 该输入数据已经存放在test.in文件中,可以直接利用进行调试
}
}
}

Windows 版本
#include <cstdio>
#include <cstdlib>
int main() {
// For Windows
// 对拍时不开文件输入输出
// 当然,这段程序也可以改写成批处理的形式
while (true) {
system("gen.exe > test.in"); // 数据生成器将生成数据写入输入文件
system("baoli.exe < test.in > a.out"); // 获取暴力代码的输出
system("youhua.exe < test.in > b.out"); // 获取要提交的程序的输出
if (system("fc a.out b.out")) {
// 该行语句比对输入输出
// fc返回0时表示输出一致,否则表示有不同处
system("type test.in"); //显示输入文件内容
system("pause"); // 方便查看不同处
return 0;
// 该输入数据已经存放在test.in文件中,可以直接利用进行调试
}
}
}

要进行对拍的两份代码
以 最大子段和 为例:
注意: 对拍时不能有freopen等输入输出从定向。
暴力代码 baoli.cpp
//最暴力的代码,保证正确性
#include<iostream>
using namespace std;
const int N = 2E6;
long long a[N];
int main(){
int n;
cin >> n;
for(int i=1;i<=n;i++){
cin >> a[i];
}
long long ans = a[1];
for(int L=1;L<=n;L++){
for(int R=L;R<=n;R++){
long long sum = 0;
for(int i=L;i<=R;i++){
sum += a[i];
}
ans = max(ans, sum);
}
}
cout << ans;
return 0;
}
优化代码 youhua.cpp
//将要提交的代码 ,本代码为有错误的代码,主要演示对拍的结果
#include<iostream>
using namespace std;
const int N = 2e6+5, INF = 0x7fffffffffffffff;
long long a[N],s[N];
int main(){
long long n, maxn = -INF,minn = INF;
scanf("%lld", &n);
for(int i=1; i<=n; i++){
scanf("%lld", &a[i]);
s[i] = s[i-1] + a[i];
maxn = max(maxn, a[i]);
minn = min(minn, a[i]);
}
long long mins=s[1], ans = a[1];
for(int i=1; i<=n; i++){
mins = min(mins, s[i]);
ans = max(ans, s[i]-mins);
}
if(ans==0) cout << maxn;
else if(minn>=0) cout << s[n];
else cout << ans;
return 0;
}
0 条评论
目前还没有评论...