【Tools】使用批处理文件对拍程序

关于对拍

OI比赛的时候经常会发生这么一种情况:
第X道题,写好了暴力并能够保证暴力的正确性,但突然想到了一个更为高效的算法,但无法确定程序是否正确,这个时候,就要使用对拍解决问题。
有些人是用c++程序进行对拍的,而我喜欢用bat文件(因为写起来短啊)。


我们假设这道题的题目名为problem,数据生成的可执行程序名为random.exe
两个程序的可执行程序名名称为problem1.exe和problem2.exe。

先发一波对拍效果图
这里写图片描述
最后一行是我打了Ctrl + C终止程序因为这样才能截图

两个版本的bat对拍

cpp内重定向写法

首先是第一种版本,就是三个源程序中都写了freopen,且random.exe的输出文件为problem.in,而两个程序所对应的输出为problem1.out和problem2.out
接下来就是对应的bat

@echo off
:loop
    random.exe
    problem1.exe
    problem2.exe
    fc problem1.out problem2.out
    if not errorlevel 1 goto loop
    pause 
    goto loop

bat内重定向写法

其次是第二种版本,就是三个程序的freopen都不被执行,相比来讲也更加随性,毕竟名字可以乱取了
对应的bat,效果和第一种是一样的。

@echo off
:loop
    random.exe > problem.in
    problem1.exe < problem.in > problem1.out
    problem2.exe < problem.in > problem2.out
    fc problem1.out problem2.out
    if not errorlevel 1 goto loop
    pause
    goto loop

两种代码可以自己参考使用,各有优劣。
对于bat内部的东西是什么意思还是解释一下吧虽然对拍这种东西靠背啊。

我拿第二个bat解释一下。
首先第一行@echo off关闭输入显示,如果你单纯地想确认一下正确性的话这句话就一定要打上,否则东西会太多的,如果不打,上结果图:
这里写图片描述
东西有点多,就很乱。。如果不想看到这种东西模糊你的眼睛就还是打上吧。
其次是第二行的:loop这是个标志,为了使用后面的goto。这个功能相信大家使用c++时一定为了好玩而使用过。
第三行random.exe > problem.in,意思是运行random.exe并将程序运行结果导入problem.in。
第四行和第五行,基本格式就是problem.exe < problem.in > problem.out,基本意思就是运行problem.exe,输入文件定向到problem.in,输出文件重定向到problem.out,说的简单点就是运行problem.exe,从problem.in中读入数据,在将程序结果输出到problem.out中。
第六行fc problem1.out problem2.outfc是比较的意思,这句话就是对两个out文件进行比较。
紧接着是第七行if not errorlevel 1 goto looperrorlevel是上一条命令的返回值,上一行的fc在比较的两个文件相同时返回0,不同时返回1,
这一行的意思就是,如果fc返回的不是1,就跳到:loop,进行下一个循环。
再下一行pause暂停,一旦fc返回1,就会执行到这一行,暂停程序,给你时间看数据。
具体效果:
这里写图片描述
goto loop,看完数据,按下任意键结束暂停,继续循环。


关于关于对拍的事儿就讲到这里,接下来贴一发在网上看到的随机数的优化。

随机数优化

优化起源:在我们写随机程序的时候会写出如下的片段:

扫描二维码关注公众号,回复: 1656336 查看本文章
        srand((unsigned)time(NULL));

或者是

        int seed = time(NULL);
        srand(seed);

可惜的是time(NULL)每秒更新1次,相当于1秒内生成的随机数据是一模一样的!这个太慢了,我们需要更优秀的随机函数。
那么有没有什么变的更快的随机数种子?有!windows自带了一个随机数发生器:%random%,它的值就是一个随机整数,可以在命令行里调用。
那接下来就好办了,我们把这个数传给rand.exe用来当随机数种子就行了。

(⊙o⊙)…怎么传参数呢?
这就要使用到c++main()函数中那个被省略的参数了。
你也许会问,main()难道省略了什么参数吗???
不好意思,答案是是的。
本来的main()应该是长成这样子的。

int main(int argc, char *argv[]) {

}

a r g c a r g v [ ] 都有什么用呢?
实际上这两个就是传入参数, a r g c 是参数个数, a r g v [ ] 是参数表,从1开始。
接下来就好办了,我们只要把%random%传给random.exe就行了。
具体操作就是把第二个bat中的random.exe > problem.in改为random.exe %random% problem.in,在random的源程序中也要对应地修改一下。板子在下面给出。


bat和random板子

bat

@echo off
:loop
    data.exe > in.txt
    solve1.exe < in.txt > out1.txt
    solve2.exe < in.txt > out2.txt  
    fc out1.txt out2.txt
    if not errorlevel 1 goto loop
    pause
    goto loop

random

#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<sstream>
#define randint(l, r) ((l) + rand() % ((r) - (l) + 1))
int main(int argc, char *argv[]) {
    int seed = time(NULL);
    if (argc > 1) {
        std::stringstream ss;
        ss.clear();
        ss << argv[1];
        ss >> seed;
    }
    srand(seed);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/diogenes_/article/details/80571645
今日推荐