<前言>
在验证猜想时,对拍可是个好工具哦!
<更新提示>
<第一次更新>新技能get✔
<正文>
对拍
关于对拍,主要是用于在考试,比赛时的程序验证,可以通过自己针对性的数据找出程序的错误之处。可以与暴力程序比较,验证自己算法或猜想的正确性,也可以在做题时放后台运行,用于检测代码是否存在错误。当你能熟练的运用对拍时,它将是一个极其有用的工具。
如何实现对拍
实现对拍,我们需要准备4个cpp文件,分别是:
1 一定正确的暴力程序(right.cpp)
2 等待验证的高分程序(test.cpp)
3 生成数据的程序(make_data.cpp)
4 对拍,检查的程序(checker.cpp)
然后我们运行right.cpp,test.cpp,得到两个exe文件,再新建一个input.in文件,作为它们共同的文件输入源。准备好这7个文件后,我们运行checker.cpp,即可进行对拍。
代码编写
right.cpp,test.cpp
根据题目需要编写。
注意,right.cpp是答案一定正确的暴力程序,test.cpp是待验证的程序。其中,我们用freopen和fclose函数来实现文件输入输出,唯一的要求是两个程序的输入文件需要相同。示例代码如下:
//right.cpp
//朴素算法实现序列的区间求和
#include<bits/stdc++.h>
using namespace std;
int main()
{
freopen("input.in","r",stdin);
freopen("right.out","w",stdout);
int n,a,b,p[10080]={},ans=0;
cin>>n>>a>>b;
for(int i=1;i<=n;i++)
{
cin>>p[i];
}
for(int i=a;i<=b;i++)
{
ans+=p[i];
}
cout<<ans<<endl;
fclose(stdin);
fclose(stdout);
return 0;
}
//test.cpp
//利用前缀和实现序列的区间求和
#include<bits/stdc++.h>
using namespace std;
int main()
{
freopen("input.in","r",stdin);
freopen("test.out","w",stdout);
int a,n,b,s[10080]={};
cin>>n>>a>>b;
for(int i=1;i<=n;i++)
{
cin>>s[i];
s[i]+=s[i-1];
}
cout<<s[b]-s[a-1]<<endl;
fclose(stdin);
fclose(stdout);
return 0;
}
切记:文件名可以由自己决定,但两个cpp文件的输入文件必须相同。(在示例中即为input.in文件)
make_data.cpp
我们利用伪随机数来生成数据,其中,生成数据的讲究有很多,已经超出了我们的探讨的范围,请自行查找相关的资料。
我们可以使用该数据生成模板:
#include<bits/stdc++.h>
using namespace std;
void make_data(int num)
{
FILE* fp=fopen("input.in","w");
srand(num);
//...
fprintf(fp,"",);
fclose(fp);
}
注意:fopen函数中的文件名可以自己定,但需要与right.cpp和test.cpp的文件输入名相同(在示例中,fopen函数的文件名必须为input.in)。然后,基本的数据生成操作就是由rand()函数生成数据,将其赋值在某个变量中,再用fprintf函数输出到文件中即可。关于rand()函数,我们只需知道它能自动生成一个104级别的随机数,我们用乘法,取模等操作得到自己想要规模的数据,使用方法为直接赋值到变量。而fprintf函数是用于输出文件,其中要在括号的最前面加上fp,后半段用法与printf函数用法相同,即fprintf(fp,"/*此处用法与printf相同*/",/*此处用法与printf相同*/)
。
对应上文,如下是一个序列区间求和的数据生成程序:
//make_data.cpp
#include<bits/stdc++.h>
using namespace std;
void make_data(int num)
{
FILE* fp=fopen("input.in","w");
srand(num);
int t=rand()%100*100,l=rand()*777%50,r=l+(rand()%38);
fprintf(fp,"%d %d %d\n",t,l,r);
for(int i=1;i<t;i++)
{
fprintf(fp,"%d\n",rand()*8848%9901);
}
fprintf(fp,"%d\n",rand()*9999%10097);
fclose(fp);
}
checker.cpp
我们主要使用system函数来调用程序并判断。
可以使用如下模板:
#include<bits/stdc++.h>
#include "make_data.cpp"
using namespace std;
int main()
{
srand(time(0));
for(int t=1;t<=N;t++)
{
make_data(rand());
system("test.exe");
system("right.exe");
printf("No:%d\n",t);
if(system("fc test.out right.out"))
{
printf("Wrong Asnwer\n");
while(1);
}
}
printf("END\n");
while(1);
}
注意:模板中N代表你需要对拍的数据组数。system函数中调用的是exe文件,文件名与cpp文件相同(在示例中,即为right.exe和test.exe),和上一节“如何实现对拍”中的一样,需要我们先运行一遍right.cpp和test.cpp来生成这两个exe文件,反复强调的文件名一定不能错。接着,if语句中的system函数一定不能忘打比较参数”fc”,比较的两个文件名为test.cpp和right.cpp所生成的输出文件(在示例中即为test.out与right.out)。这样就完成checker.cpp了。
对应上文,如下是一个对拍5000组数据的检查程序:
//checker.cpp
#include<bits/stdc++.h>
#include "make_data.cpp"
using namespace std;
int main()
{
srand(time(0));
for(int t=1;t<=5000;t++)
{
make_data(rand());
system("test.exe");
system("right.exe");
printf("No:%d\n",t);
if(system("fc test.out right.out"))
{
printf("Wrong Asnwer\n");
while(1);
}
}
printf("END\n");
while(1);
}
运行与使用
运行checker前,在检查一遍是否准备好了文件,4个cpp,2个exe,一个自己建的空文件作为两个运行程序的共同输入源,数据生成的输出源(在示例中,即为input.in)。接着运行checker.cpp,开始对拍。
在运行过程中,如果没有错误,对拍会自动进行,可以放在后台运行,如果出现错误,对拍会自动停止,按ctrl+c退出,然后你就可以在数据生成的输出源中找到使你程序出错的那一组数据(在示例中即为input.in)。
注意了,所有文件在同一目录下哦!
对拍的效果如图哦。
<后记>
<废话>