关于对拍
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.out
,fc
是比较的意思,这句话就是对两个out文件进行比较。
紧接着是第七行if not errorlevel 1 goto loop
,errorlevel
是上一条命令的返回值,上一行的fc
在比较的两个文件相同时返回0,不同时返回1,
这一行的意思就是,如果fc
返回的不是1,就跳到:loop
,进行下一个循环。
再下一行pause
暂停,一旦fc
返回1,就会执行到这一行,暂停程序,给你时间看数据。
具体效果:
goto loop
,看完数据,按下任意键结束暂停,继续循环。
关于关于对拍的事儿就讲到这里,接下来贴一发在网上看到的随机数的优化。
随机数优化
优化起源:在我们写随机程序的时候会写出如下的片段:
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[]) {
}
和
都有什么用呢?
实际上这两个就是传入参数,
是参数个数,
是参数表,从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;
}