SPJ 学习笔记

· · 个人记录

今天来简单介绍一下常用的 Sepcial Judge 的写法,这里使用的是 Lemon 测评软件。

什么是 Special Judge

一般的奥赛题目中,若是答案唯一,那么在检查程序输出是否正确时,只需要比对输出文件和答案文件是否完全一致即可。然而,在部分情况下,答案可能不唯一,或者允许答案有一定的误差,这时,就需要“特判”,需要我们自己写一个程序来检查答案是否正确。

一般的,OJ 上都已经配置好了 SPJ,但是在自己出题、出比赛的时候,难免要自己写一个,因此今天做一个简单的学习。

一个例子

以整数形式给定圆的半径,输出该圆的周长,该圆的面积。精度误差不超过 10^{-6}

先展示一下目录:

然后放一下代码:

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 使用 实践 入门