前言
近期考古发现,本人于2017年3月水了一篇对拍。
我发现它实在是水,估计没多少人看得懂。
作为一个内心善良,乐于助人,无比有爱心的人。
我决定再水一篇对拍。
本文废话较多,代码较恶心,诸君可以跳跃性阅读。
对拍
解释
根据百度汉语对“拍”的解释,好像无法理解这个词。
简单来说,就是写一个数据生成器,然后把生成的数据给两个不同的程序运行,比较它们输出的结果。
主要有两个用途:
- 比赛(考试)时,写了一个自以为正确的程序,但是还是不放心,可以再写一个暴力程序,对拍验证。
- 做题做到天昏地暗,头晕目眩,不分东南西北之时,眼前一片血红,于是不小心偷了一个充满生命力的代码,再写个数据生成器,说不定对拍能挽救代码的生命。
例题
A+B Problem
数据生成器
方法
生成随机数之必备武器:ctime
、cstdlib
。
在main
开头写:
srand((unsigned)time(NULL));
意思大概是设置随机数的种子为你的时间。
如果你不写或者写个srand(1234567)
,你发现你每次生成的“随机数”都是一样的。
然后使用:
int x=rand();
就可以得到一个
0
0
0到不知道多少(RAND_MAX
)的整数。
如果你想得到得到
[
a
,
b
]
[a,b]
[a,b]之间的一个整数:
int x=rand()%(b-a+1)+a;
如果 a , b a,b a,b有些大,可以这样,以防数据太弱:
int x=1ll*rand()*rand()%(b-a+1)+a;
如果想得到浮点数,除以 10 10 10即可。
当然,如果想要生成一个树、一个连通图、一个二分图什么的,加点数据结构之类的就行了 。
曾经我为了对拍一个破圈法的题,写了100多行的数据生成器。
代码
#include<ctime>
#include<cstdio>
#include<cstdlib>
#define MAXN 1000
int main(){
srand((unsigned)time(NULL));
int A,B;
A=rand()%MAXN;
B=rand()%MAXN;
printf("%d %d\n",A,B);
//想像一下用手输数据的时候不打换行会怎么样,这里就会怎么样
}
你的程序 == WA
什么都不用加,找的你的程序的exe
文件即可。
#include<cstdio>
int main(){
int a,b;
scanf("%d%d",&a,&b);
printf("%d",a/b*b+b);
}
我的程序 == AC
什么都不用加,偷到我的程序的exe
文件即可。
没有时间了,只好先水一个SPFA
,如有错请见谅 。
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAXM 2
#define MAXN 3
struct Edge{
int v,w;
Edge *Next;
}E[MAXM+5];
Edge *ecnt,*First[MAXN+5];
void Init(){
ecnt=&E[0];
memset(First,0,sizeof First);
}
void AddEdge(int u,int v,int w){
++ecnt;
ecnt->v=v,ecnt->w=w;
ecnt->Next=First[u],First[u]=ecnt;
}
int dist[MAXN+5];
bool vis[MAXN+5];
int SPFA(int S,int T){
memset(vis,0,sizeof vis);
memset(dist,0x3f,sizeof dist);
queue<int> Q;Q.push(S);
dist[S]=0,vis[S]=1;
while(!Q.empty()){
int u=Q.front();
Q.pop();vis[u]=0;
for(Edge *i=First[u];i!=NULL;i=i->Next){
int v=i->v,w=i->w;
if(dist[v]>dist[u]+w){
dist[v]=dist[u]+w;
if(!vis[v]){
vis[v]=1;
Q.push(v);
}
}
}
}
return dist[T]==0x3f3f3f3f?-1:dist[T];
}
int main(){
int a,b;
scanf("%d%d",&a,&b);
Init();
AddEdge(1,2,a);
AddEdge(2,3,b);
printf("%d",SPFA(1,3));
}
AC
证明:
对拍程序
其实我的续集只是续的这个部分。
古文《对拍》中,是使用的C++
写对拍,各位是不是感觉很慢?看上去很不爽?还要编译?
所以现在使用bat
文件完成对拍,Windows下有一个命令:fc
,可以比较两个文件。
准备活动
方法:
- 在一个你喜欢的位置新建一个记事本文件
dp.txt
- 将后缀
.txt
改成.bat
,所以你的文件变成了dp.bat
这个时候问题来了:
我的文件是这样的嘤嘤嘤:
这样做:
随意打开一个文件夹
→
\to
→(左上角)组织
→
\to
→文件夹和搜索选项
→
\to
→(上方)查看
→
\to
→下面的高级设置中找到“隐藏已知文件类型的扩展名”,把前面的勾去掉即可。
然后你就会发现变成了这样:
把.txt
改成.bat
:
代码
继续:
- 右键
dp.bat
,点击“编辑”
接下来才是重点。
仔细观察你即将粘贴进去的代码:
@echo off
:loop
数据生成器位置 > data.txt
你的程序的位置 < data.txt > yours.txt
我的程序的位置 < data.txt > mine.txt
fc yours.txt mine.txt
if not errorlevel 1 goto loop
pause
goto loop
你急用就直接粘过去,如果你希望考试的时候能用就继续看。
示例
@echo off
:loop
C:\3\bin\Debug\3.exe > data.txt
C:\1\bin\Debug\1.exe < data.txt > yours.txt
C:\2\bin\Debug\2.exe < data.txt > mine.txt
fc yours.txt mine.txt
if not errorlevel 1 goto loop
pause
goto loop
注意一定要填exe
文件。
把上面的代码保存后,直接双击dp.bat
。
你一定看懂了它的意思。
这时打开data.txt
,里面是你的数据生成器生成的数据,yours.txt
和mine.txt
分别是你的输出结果和我的输出结果。
当然,你可以“按任意键继续”。
如果输出一样是什么效果请自行试验。
更多内容
这里个人是对对拍代码的解读,更准确的内容请百度。
@echo off
:此句可不要,但会多输出一些提示性语句。echo
有回声的意思,应该是指回显,而off
就是关闭。至于为什么fc
的回显没有关闭,不知道= =:loop
和goto loop
:等于C++
的loop:
和goto loop
,相当于循环。<
和>
:大概是运行后输入输出之意。fc FILE1 FILE2
:比较FILE1
和FILE2
。if not errorlevel 1
:大概是看fc
的“返回值”,判断两文件是否相同。pause
:按任意键继续
以上语句全部可以通过C++
的system
函数运行,效果相同。
后记
感谢你阅读到了这里(可能你是一下子拉到底的),本文确实废话较多,但是之前的《对拍》有些内容确实不太优秀,我又不忍心删掉它,所以写了这样一篇。