SPJ 学习笔记
今天来简单介绍一下常用的 Sepcial Judge 的写法,这里使用的是 Lemon 测评软件。
什么是 Special Judge
一般的奥赛题目中,若是答案唯一,那么在检查程序输出是否正确时,只需要比对输出文件和答案文件是否完全一致即可。然而,在部分情况下,答案可能不唯一,或者允许答案有一定的误差,这时,就需要“特判”,需要我们自己写一个程序来检查答案是否正确。
一般的,OJ 上都已经配置好了 SPJ,但是在自己出题、出比赛的时候,难免要自己写一个,因此今天做一个简单的学习。
一个例子
以整数形式给定圆的半径,输出该圆的周长,该圆的面积。精度误差不超过
先展示一下目录:
然后放一下代码:
SPJ:
#include <bits/stdc++.h>
using namespace std;
FILE* fin;//标准输入
FILE* fout;//用户输入
FILE* fstd;//标准输出
FILE* fscore;//得分文件
FILE* freport;//报告文件
void quit(int x)
{
fprintf(fscore,"%d",x),fclose(fin),fclose(fout);
fclose(fstd),fclose(fscore),fclose(freport),exit(0);
}
int del = 1e-6;
bool Judge()
{
//这里是 check
double a,b,aa,bb;
fscanf(fout, "%lf %lf", &a, &b);
fscanf(fstd,"%lf %lf",&aa,&bb);
if(fabs(a-aa)<=del && fabs(b-bb)<=del)
return true;
else
return false;
}
int main(int argc,char*argv[])
{
//argv 中存储了这个测试点的各种信息
//argc 是干什么的我还不太清楚
fin=fopen(argv[1],"r");//标准输入
fout=fopen(argv[2],"r");//用户输入
fstd=fopen(argv[3],"r");//标准输出
int score = atoi(argv[4]);
fscore=fopen(argv[5],"w");//得分文件
freport=fopen(argv[6],"w");//报告文件
if(Judge()) fprintf(freport,"OK"),quit(score);
else fprintf(freport,"WA"),quit(0);
}
源程序:
#include<bits/stdc++.h>
using namespace std;
const double pi = 3.1415926535;
int r;
int main(){
freopen("A.in","r",stdin);
freopen("A.out","w",stdout);
scanf("%d",&r);
printf("%lf %lf\n",r*pi*2,r*r*pi);
return 0;
}
其实比较简单,大概是因为 Lemon 里已经做好了接口吧。主函数的部分对于任何 SPJ 都是相同的,只需要修改 Judge 函数中的具体检查部分就可以了。
这里涉及到了一部分文件操作的知识,可以参考这篇文章中的内容:C++文件读写操作总结
将这个文件命名为 SPJ_for_A,然后把这个文件编译得到的 .exe 文件放到 data 文件夹中的对应题目的文件夹下:
然后来看一下 Lemon 里的文件配置:
选择自定义校验器模式,在下面出现的空行里输入 “题目名称\SPJ.exe”,这样就配置好了。
最后尝试测试一下看看结果:
当然,你也可以把源程序中的 π 改成 3.14,结果会是 WA。
参考文献:
C/C++文件读写操作总结:FILE*、fstream、windowsAPI
Lemon LemonLime 中 SPJ Special Judge 使用 实践 入门