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


    对拍是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了。

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

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

  • 相关阅读:
    Android标题栏最右边添加按钮
    Activity标题栏添加返回按钮
    【Android】解决Android横竖屏切换数据丢失问题的方法
    Android热更新,到底是更新啥?
    vm ware 虚拟WIN10 时,chrome ,cent browser 显示异常,花屏
    动态生成的 select option 无法选中,设置值
    安装sql 2012 时遇到“需要更新的以前的 Visual Studio 2010 实例。”规则失败。
    C#.NET 简单使用log4net
    10位,13位时间戳转为C#格式时间
    C# .NET Unix 时间戳
  • 原文地址:https://www.cnblogs.com/OIerShawnZhou/p/7618019.html
Copyright © 2020-2023  润新知