对于当正确的输出结果不唯一的时候,我们就需要使用自定义校验器们,也就是我们常说的Special Judge。一般来说我们需要自己编写Special Judge的判断程序,不同的评测系统对于Special Judge的要求也不一样,下面就来谈一谈Cena和Lemon的Special Judge。
Cena
首先,Cena的帮助里面是这样说的:
3.2.2 自定义校验器说明
获取必要的信息
待测的测试点的最高分 ParamStr(1)(Pascal) 或 argv1
标准输出文件名 ParamStr(2)(Pascal) 或 argv2
标准输入和选手输出同数据配置。
结果返回
得分返回文件 score.log 只有一行,为这个测试点的得分。可使用小数。
返回校验信息 report.log 若没有此文件,或此文件的内容为空,则没有校验信息,反之则将在评测结果右侧显示“(?)”,点击则显示信息。(参见: 查看评测结果)。
交互单元
本评测系统提供了编写校验程序的交互单元,以方便使用 Pascal 语言编写自定义校验程序。
libcheck.pas(位置:安装路径\lib) 说明如下:
变量:
std: Text; { 用于读取标准输出文件 }
rep: Text; { 用于写入校验信息 }
fso: Double; { 为这个测试点的满分 }
过程:
procedure Score(AScore: Double); { 用于向评测系统报告得分 }
procedure Finish; { 结束 }
使用举例 (Pascal语言):
uses
libcheck;
var
a,b,c,stc: integer;
begin
assign(input, 'add.in'); { 试题的输入文件名 }
reset(input);
readln(a, b);
close(input);
assign(input, 'add.out'); { 试题的输出文件名,由选手程序输出 }
reset(input);
readln(c);
close(input);
read(std,stc); { 从标准输出文件中读取标准答案 }
writeln(rep,'这个测试点的输入为:',a,' ',b);
writeln(rep,'标准输出为:',stc);
writeln(rep,'选手输出为:',c);
if stc=c then begin
writeln(rep, '正确。');
Score(fso); { 得满分 }
end
else begin
writeln(rep, '错误。');
Score(0); { 得 0 分 }
end;
writeln(rep, '本自定义校验程序由 *** 提供。仅供示例。');
Finish;
end;
建议
请使用 32 位编译器(如 Free Pascal, Delphi, GCC )来编译您的校验程序,以加快评测的速度。
简单地来说,就是:
“score.log” 输出最终得分
“report.log”输出错误报告
#FILENAME”.in”输入文件
#FILENAME”.out”选手输出文件
argv[2]:标准输出文件
argv[1]:单测试点分值
下面是一个我用的板子
#include<cstdio>
#include<cstdlib>
#include<cmath>
FILE *fscore,*freport,*fstd,*fin,*fout;
int Judge()
{
fscanf(fstd,/*******/);
fscanf(fout,/*******/);
//judge函数
}
int main(int argc,char *argv[])
{
fscore=fopen("score.log","w"); //打开得分文件
freport=fopen("report.log","w");//打开报告文件
fstd=fopen(argv[2],"r"); //打开测试点标准输出文件
int score=atoi(argv[1]); //取得测试点的分数
fin=fopen("circle.in","r"); //打开测试点标准输入文件
fout=fopen("circle.out","r"); //打开用户的数据输出文件
if (!fout)
{
fprintf(fscore,"%d",0); //返回0分
fprintf(freport,"没输出你交上来干啥");//报告Judge结果为no output
}
else if (Judge()==1) //Judge后结果为真
{
fprintf(fscore,"%d",score);//返回满分
fprintf(freport,"太厉害了,被你A了"); //报告Judge结果为right
}
/*部分分
else if (Judge()==-1)
{
fprintf(fscore,"%d",score<<1);//返回部分分
fprintf(freport,"你可能被卡精度了");
}
*/
else if (Judge()==0)
{
fprintf(fscore,"%d",0); //返回0分
fprintf(freport,"你愉快地WA了");//报告Judge结果为wrong
}
fclose(fscore);//关闭得分文件
fclose(freport);//关闭报告文件
return 0;
}
写好之后我们只需要把SPJ程序放到Data文件下,注意一定要运行生成exe文件。
然后把比较方式换成使用自定义校验器
然后就可以了
Lemon
这个我也不是很熟悉
所有的都从argv[]里面读入
argv[1]:输入文件
argv[2]:选手输出文件
argv[3]:标准输出文件
argv[4]:单个测试点分值
argv[5]:输出最终得分的文件
argv[6]:输出错误报告的文件
然后lemon的spj就大概这样写
int main(int argc,char *argv[]){
fin.open(argv[1]);
fout.open(argv[2]);
fstd.open(argv[3]);
fscore.open(argv[5]);
freport.open(argv[6]);
int score=atoi(argv[4]);
fscore<<score*Judge()<<endl;
fin.close();
fout.close();
fstd.close();
fscore.close();
freport.close();
retur