前置知识
引入
假设你现在正站在某大型比赛的赛场上,面对着屏幕前的世纪难题大汗淋漓,对正解毫无思路,这时你应该怎么办呢?
在这样的情况下,你应该写出一个暴力代码,尝试骗得一部分分数。
然而,不甘于平凡的你怎能只获得可怜的 20 p t s 20pts 20pts呢?你要拿 100 p t s 100pts 100pts。
你绞尽脑汁,想到了一个“疑似正解”,这时你要怎么确定它是否是正解呢?
为了你的宏图伟业,你就要学习这样一种东西:对拍
对拍
对拍是干什么用的呢?
你写了一个暴力和一个“疑似正解”,你确定你的暴力是正确的,这时你要确定你的“疑似正解”是否正正确,这时你需要将暴力和“疑似正解”都输入相同的数据,看它们的输出是否相同。如果对于很多组数据都有相同的输出,我们就可以认为这个“疑似正解”应该就是正确的。
对拍由四部分组成:
- 一个随机数据生成器
- 你的暴力
- 你的“疑似正解”
- 对拍程序
我们以世纪难题为例,来尝试实现对拍。
首先,我们需要一个数据,注意,这个数据的范围不与题目的数据范围相同,而是要根据你的暴力,你的暴力要很快的将这个数据运行完毕,这样才能保证对拍的效率。
为了保证每次生成的数据都不同,我们要进行随机取值。具体参见随机数。
我们将产生数据的代码命名为shujv.cpp,那么它编译出的EXE文件为shujv.exe,我们还要将产生的数据输出到一个TXT文件里,命名为shujv.txt。
shujv.cpp内容如下:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;
int main()
{
srand(time(0));
freopen("shujv.txt","w",stdout);
int a=rand()%1000+1;
int b=rand()%1000+1;
cout<<a<<' '<<b<<endl;
return 0;
}
然后是你的暴力文件,命名为baoli.cpp,可执行文件为baoli.exe,读入数据为shujv.txt,输出数据为baoli.txt:
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
freopen("shujv.txt","r",stdin);
freopen("baoli.txt","w",stdout);
int a,b;
cin>>a>>b;
int c=0;
for(int i=1;i<=a;i++)
c++;
for(int i=1;i<=b;i++)
c++;
cout<<c;
return 0;
}
“疑似正解”文件同理,为std.cpp、std.exe、shujv.txt、std.txt:
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
freopen("shujv.txt","r",stdin);
freopen("std.txt","w",stdout);
int a,b;
cin>>a>>b;
cout<<a+b;
return 0;
}
这时,就是最关键的部分了:对拍程序!我们要重复执行下面的步骤:
- 制造数据,即运行
shujv.exe文件 - 运行
baoli.exe - 运行
std.exe - 判断
baoli.txt和std.txt是否相同
对于前三条,只需要使用system打开即可,而第四条,则需要使用fc指令,详见代码:
#include<windows.h>
using namespace std;
int main()
{
while(1)
{
system("shujv.exe");
system("baoli.exe");
system("std.exe");
if(system("fc baoli.txt std.txt"))//判断是否相同
break;//若不同则跳出
}
return 0;
}
全部完成后,文件如下:

这时我们要把除了对拍程序外的所有程序运行一遍,产生EXE文件:

然后运行对拍程序,如果顺利,如下:

如果如上图,恭喜你,你的正解没问题。
如果出现错误,程序会停止:

这时你就可以打开数据寻找错误了。
本文介绍了在编程比赛中如何使用对拍技术验证算法的正确性。通过对暴力解和疑似正解输入相同数据并比较输出,来确认疑似正解是否正确。文中详细阐述了对拍的组成部分和实现步骤,并提供了相关程序文件的命名和生成数据的方法。
1011

被折叠的 条评论
为什么被折叠?



