可以配合如何优雅的造数据食用qwq。
前言
- 什么是对拍?
通俗来讲就是,你写了一份的正解,但是你不知道这个正解对不对,代码有没有写挂。
通常情况下你可能会考虑手造几个样例跑一跑试试。
但手造样例有时候又太弱,于是我们采用另一种方式。
你手写一个暴力。暴力的正确性肯定有保证对吧。
然后你写一个随机数据生成器,生成多组数据,同时运行暴力和正解,比较他们的输出结果是否相同,来反向证明正解有没有写挂。
然后这个过程就叫对拍。
- 怎么写?
据我所知有两种形式,一种是在文本文档编辑,.bat
类型的对拍。
另一种是直接用 C++ 写的对拍。
接下来我们主要介绍第二种,用起来对我们会方便一些。
第一步:放入要验证的程序和暴力
找到自己的暴力和yy的正解, 分别放入std和test两个cpp中
(以 A + B Problem 为例)
#include <iostream>
using namespace std;
int main()
{
freopen("in.in","r",stdin); // 读入生成的随机数据
freopen("std.out","w",stdout);//这里是 std 的输出文件
int a,b;
cin >> a >> b;
cout << a+b << endl;
return 0;
}
#include <stdio.h>
int main()
{
freopen("in.in","r",stdin); // 读入生成的随机数据
freopen("test.out","w",stdout);//这里是自己写的暴力的输出文件
int a, b;
scanf("%d %d",&a, &b);
printf("%d\n", a+b);
return 0;
}
第二步:造出随机数据
然后写一个用来创造随机数据的cpp,起名为 data (起名不重要)
#include<cstdio>
#include<cstdlib>
#include<ctime>
int main()
{
freopen("in.in","w",stdout); //创建一个 in.in 文本文档来存放我们的随机数据
srand(time(0));
// 这是一个生成随机数随机种子,需要用到 ctime 库
// 这句话会保证每次的数据都是随机的。如果不加,每次调用相同的种子,生成的数据是不变的。
printf("%d %d\n",rand(),rand());
// 这样就生成了我们需要的输入样例
return 0;
}
第三步:进行文本对比
然后使用下面这个对拍程序
如果测试多组数据后程序仍然没有退出,恭喜,您的正解很可能是对的
如果测试几组数据后程序会停止运行,并会反馈两个输出不一样的地方。
此时关掉正在运行的窗口,打开in.in文件,就可以查看Hack数据了。
#include<bits/stdc++.h>
#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;
int main()
{
// int T = 0;
while(1) //一直循环,直到找到不一样的数据
{
// cout << ++T;可以加一个计数器
system("data.exe");// 运行 data.exe,生成数据
system("test.exe");// 运行test.exe,跑一边正解,得到正解的输出结果
system("std.exe");// 运行std.exe,跑一边暴力,得到暴力的输出结果
if(system("fc std.out test.out"))
// 这个语句的实际意思就是比较 std.out 和 test.out 的内容是否相同
// 当 fc 返回 1 时,说明这时两个输出不同,返回值为 true
break; //不一样就跳出循环
}
return 0;
}
有什么问题欢迎提出。
鸣谢
感谢 Imy_bisLy
提供的技术与资源支持