正常向的对拍方法 学习笔记

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了正常向的对拍方法 学习笔记相关的知识,希望对你有一定的参考价值。

对拍是OI系列赛事常用的检验方法之一,它用来检验自己写的“正解”到底正不正确。简要的说,就是用一个脚本文件比对两个输出结果来判断正确性。

要使用对拍,必须要有一个保证正确的暴力程序作为参照,这个程序虽然正确,但是由于时间复杂度较高所以无法拿到很高的分数,一般是拿到题后首先想到的比如暴力搜索之类的算法。而我们要比对的程序就是自己在冷静分析后所写出来的所谓“正解”,如果你无法证明这个算法是显然正确的,那么对拍就可以帮助你验证它的正确性。

那么对拍需要准备的工具都是啥呢?

首先,我们需要两个源程序,第一个是作为参照的暴力程序,第二个是我们写完的所谓“正解”但正确性未知的程序。

既然要比对输出,那么比较工具自然少不了,这个比较工具就是上面我说的脚本文件,不过这个东西并不是用C++语言写出来的。简要来说,它接收一个输入数据,然后分别在两个程序中运行,然后判断输出结果是不是一致。如果你的正解和暴力解法输出不一致,那么你的解法就有可能存在问题。

其实还缺一个最重要的东西,那就是数据生成器。巧妇难为无米之炊,比较器如果没有输入数据是没办法比较的,所以我们还得根据输入格式自己制造数据。

这就牵扯到随机数生成的问题了,我在之前的博客里使用过随机数生成的程序,我记得当时应该是用来做读入性能测试。我再后来给学校暑期模拟赛出题,自己造数据的时候也用到过随机数生成。

两个比对程序是根据题目自己写出来的,这个因题而异,我在这里用A+B问题举例。

我们知道,在实际的比赛中要使用文件操作,对拍程序也需要程序的输入和输出文件来进行比较(当然有重定向版本的对拍脚本不需要文件,我这个不是。。)

首先我写了一个作为标准的程序。

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 int a,b;
 5 int main(){
 6     freopen("randdata.out","r",stdin);
 7     freopen("std.out","w",stdout);
 8     cin >> a >> b;
 9     cout << a + b << endl;
10     return 0;
11 }

这个a+b没毛病吧。

然后我故意制造一个bug。

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 int a,b;
 5 int main(){
 6     freopen("randata.out","r",stdin);
 7     freopen("problem.out","w",stdout);
 8     cin >> a >> b;
 9     10     if (a+b > 1926)
11         cout << "-1" << endl;
12     else
13         cout << a+b << endl;
14         
15     return 0;
16 }

可以看出,它们都读入一个叫randdata.out的文件,这个文件就来源于下面这个程序。

#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <iostream>
#include <unistd.h>
#include <windows.h>
#define random(x) (rand()%x+1)
using namespace std;
int main(){
    srand(time(NULL));
    int a,b;
    a = random(2000);
    b = random(2000);
    freopen("randdata.out","w",stdout);
    printf("%d %d",a,b);
    return 0;
}

具体要生成什么格式的数据还是就题论题,但大体的思路还是一致的,即随机数生成。

如果要生成一个合法的树或者图,可能需要一些算法。我如果没记错的话luogu有一个开源的数据生成器CYaRon,那里面有pyhton3.x版本的生成这些数据结构的代码,借鉴思想后将其转换至C++语言是一个不错的方法,您大可拿来一试。

对拍所用的脚本其实是根据系统的不同而有差异的,在windows下的脚本和在linux下的脚本写法不太一样。

我并不是一个linux用户(以后不一定不是),所以linux版本的对拍脚本并不是很熟悉,这里只提供windows版本的对拍脚本,有兴趣研究linux下对拍者请自行查阅其他资料。

下面是windows下对拍脚本一般写法。

@echo off
:start
randdata.exe 
problem.exe 
std.exe
@echo %time%
fc problem.out std.out
if not errorlevel 1 goto start
pause

@echo命令我记得是防止信息重复输出的。:start相当于一个记号,下面三个.exe文件就是我们编译之后的源程序,你应该先执行数据生成器程序,再执行两个等待评判的程序。

如果一切正常,那么这个时候三个程序都会输出一个.out文件。

倒数第三行的fc命令便是鉴别两个文件是狗不同,如果两个文件相同,那么就再回到start再生成一次数据测试。

倒数第四行为输出时间,可以不加。

如果找到不同,那么就pause了。

 

最后,上述可执行程序和对拍脚本应该放在同一文件夹下执行,否则不能执行。

如果您对对拍代码难以理解,那还请您背过,因为它很重要,这是在考场上为数不多的检验自己程序正确性的方式。

以上是关于正常向的对拍方法 学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

浴谷国庆集训 对拍

『工具』对拍器

[科技]NOI Linux下的对拍程序

模板对拍程序

对拍源码QwQ

How to 对拍?