在我不会对拍的时候,我觉得这是大佬学校才会教的东西。 ——hzz
这篇文章主要是想批量教我校同学对拍。(懒
鉴于我校日常练习环境就是NOIlinux,我就不讲Windows的Bat了。(其实自己也不太会Bat
建议各位大佬把主程序改成自己的风格再背(不然哪里背的住啊摔
/////////////////////////////////////////(///v///)//////////////////////////////////////////////
首先,假设你已经完成了一道题的100%数据,你给这个文件取名为test.cpp
在test.cpp中,你也已经打好了freopen,读入文件为test.in,输出文件为test.out。
这时候你害怕自己因为一些小问题而不能AK这场比赛。你决定使用听起来很厉害的对拍。
对拍呐,就是让你的代码跟暴力一起算它几百个数据。如果你的代码和暴力的结果不一样,那你就错了。 ——hzz
/////////////////////////////////////////开始(///V///)搞事//////////////////////////////////////////////
首先,为了跟你的高级程序作对比,你需要一个对小数据保证正确的对比程序(俗称暴力)。
它通常非常好打,也非常慢。
我们把它取名为std.cpp
在这里面,你也乖巧的打好了freopen。为了跟高级的程序作对比,你把它的输出文件取名为test.ans。
这时候,两位选手已经就位,你还需要一位出题人。
我们把它取名为rand.cpp
/////////////////////////////////////////以下,我们以A+B Problem为例(///V///)//////////////////////////////////////////////
我们想让rand生成测试数据,那么只需要:
1 //rand.cpp 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<ctime> 6 using namespace std; 7 int main() 8 { 9 freopen("test.in","w",stdout); 10 srand(time(NULL));//给rand赋时间种子。(不然rand出来的数不变 11 int max=1e9; 12 int a=rand()%max,b=rand()%max;//让a变成0~max-1的任意一个数,对b同理。 13 cout<<a<<" "<<b;//输出到test.in 14 return 0; 15 }
它就能勤奋的生成测试数据啦!
/////////////////////////////////////////接下来(///v///)才是精华呐//////////////////////////////////////////////
那么,我们怎样让这三个程序一起跑起来呢?
我们需要一个对拍程序,我们把它取名为pai.cpp
它里面长这样↓
1 //pai.cpp 2 #include<bits/stdc++.h>//万能头文件 3 using namespace std;//别忘了这个鸭!!(血泪教训 4 #define Run(cmds) for(int i=0;i<sizeof(cmds)/4;++i) {system((cmds[i]));}//这句话我也读不懂(逃 5 char *build[]{//定义一个叫build的命令组,用于编译三个文件 6 "g++ -o test test.cpp",//编译test.cpp 7 "g++ -o rand rand.cpp",//编译rand.cpp 8 "g++ -o std std.cpp -O2"//编译std.cpp(毕竟它是暴力,建议开O2 9 };//记得分号 10 char *randata[]{//一个叫randata的命令组,用于生成输入数据和答案 11 "./rand > test.in",//运行rand,输出到test.in 12 "./std < test.in > test.ans"//运行std,从test.in输入,输出到test.ans 13 }; 14 int main() 15 { 16 Run(build);//先都编译一下 17 int runtime=1e3;//拍的次数 18 for(int s=1;s<=runtime;++s) 19 { 20 Run(randata);//rand一下 21 printf("Case %d:",s);//输出一下当前测到第几组了 22 if(system("./test < test.in > test.out")!=0)//如果运行test返回的值不是0 23 {cout<<"RE"<<endl;break;}//RE了,break掉 24 else if(system("diff -b test.out test.ans")!=0)//如果a.out和a.ans不一样(-b是忽略结尾空格和回车 25 {cout<<"WA"<<endl;break;}//WA了吖QAQ 26 else cout<<"AC"<<endl;//这组跑过去啦 27 } 28 return 0; 29 }
才二十几行!核心才二十几行!//超级良心
UPD:如果搞不懂那个#define Run或者就是想背的短一点的话可以改成这样↓
1 //pai.cpp 2 #include<bits/stdc++.h> 3 using namespace std; 4 int main() 5 { 6 system("g++ -o test test.cpp"); 7 system("g++ -o rand rand.cpp"); 8 system("g++ -o std std.cpp -O2"); 9 int runtime=1e3; 10 for(int s=1;s<=runtime;++s) 11 { 12 printf("Case %d:",s); 13 system("./rand > test.in"); 14 system("./std < test.in > test.ans"); 15 if(system("./test < test.in > test.out")!=0) 16 {cout<<"RE"<<endl;break;} 17 else if(system("diff -b test.out test.ans")!=0) 18 {cout<<"WA"<<endl;break;} 19 else cout<<"AC"<<endl; 20 } 21 return 0; 22 }
QAQ
————————让我们来(///v///)试用一下————————
首先我们把这四个文件放在同一个文件夹里。
然后调用终端,打开这个子目录。
编译这个叫做pai的核心程序。
之后会出一长串的Warning,不用害怕,仔细看一下有没有error就行了。
//真的很长一串
这时候如果有报错,就是pai.cpp写炸了。
确定没有error之后,我们运行pai.cpp
——————跑啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊——————
如果一切完美,那么你会在终端上看到这样一幕——
当然事情不总是这么简单的。
如果你另外三个程序有锅,它就会提醒,同时显示RE。
eg:
照着它的提示改好就可以了。
>w<
如果你不幸的WA了:
它会这样显示。
1c1 //line 1 column 1
<914 //test.out给的结果
>915 //test.ans给的结果
如果两文件都多处不同,它都会显示出来。
这时候就只好去改程序啦QAQ
到此这篇简陋教程就结束啦。
这就是我会的全部对拍技巧了,应该够用了,
不过我还是不会让它提示我TLE了或者MLE了QAQ
所以真的很简陋的吖QAQ