前言
做好了题目,测试点怎么做呢?
本文章含有:制作测试点的基本步骤、测试点的配置、自定义计分脚本、Special Judge、交互库
基本测试点
首先需要创建几个.in
和.out
文件,.in
是要输入的内容,.out
是程序应该输出的内容。
名字可以直接是 001.in 001.out 002.in 002.out 003.in 003.out
,也可以在数字的前面添加一些字母,如test001.in test001.out
。
以
P
1001
A
+
B
p
r
o
b
l
e
m
P1001~A+B~problem
P1001 A+B problem 为例.
001.in
可输入:
1 1
001.out
可输入:
2
002.in
可输入:
7 8
002.out
可输入:
15
做好了测试点,需要创建一个.zip
类型压缩包(.rar
不行),打包上传,压缩包的名字随意,我一般取题目编号。
测试点配置
网页直接配置
每个测试点都可以设置时间限制(ms)、空间限制(MB)、子任务(基本上就是给测试点一个分类)和分值(如果做对了得多少分)。
上传之后会显示,里面会有一个默认值,可以改,如果想让所有测试点都遵照一个,可以在最上面那个空写。
配置文件
配置文件的名字必须是config.yml
,放在测试点压缩包中,格式为:
001.in:
timeLimit: 10
memoryLimit: 1024
isPretest: false
subtaskId: 3
score: 50
002.in:
subtaskId: 0
score: 50
- timeLimit是时间限制,以ms为单位
- memoryLimit是空间限制,以KB为单位
- isPretest,就是是否为Pretest测试点,true or false
- subtaskId是属于哪一个子任务
- score是分值,做对了有几分
- 如果有任何一个信息没有写的话,那么将会把没有写的信息设置为默认。
自定义计分脚本
可在Subtask里选自定义计分方式,然后在右边的框里写。
例:
if (@status4 == AC) and (@status3 == AC or @status5 == AC); then
@total_score = 30;
@final_status = AC;
@final_time = @time4;
@final_memory = @memory4;
else
@total_score = 0;
@final_status = UNAC;
@final_time = 0;
@final_memory = 0;
fi
语法:
- fi为结束判断
- 可使用加减乘除取模、and or not xor、== >= <= != > <,优先级均与C相同
常量:
测试点:
- AC:通过
- WA:答案错误
- TLE:超时
- MLE:超内存
子任务:
- AC:通过
- UNAC:不通过
变量:
- @total_score是该Subtask的总得分
- @final_status是该Subtask的最终状态
- @final_time是该Subtask的最终用时
- @final_memory是该Subtask的最终内存
- @status x x x是测试点x状态
- @score x x x是测试点x得的分
- @time x x x是测试点x的所用时间
- @memory x x x是测试点x的所用空间
Special Judge
Testlib头文件(不用下载也可以)
名字必须是checker.cpp
,放在测试点压缩包中,题目还要加上Special Judge
标签,格式为:
#include "testlib.h"
using namespace std;
int main(int argc,char *argv[]){
registerTestlibCmd(argc,argv);
setName("out with ans xiangcha not 0.1");
while(!ans.eof()){
double out=ouf.readDouble();
double answer=ans.readDouble();
ans.readEoln();
if(fabs(answer-out)>0.1)
quitf(_wa,"wrong, ans:%lf, out:%lf",answer,out);
}
quitf(_ok,"This is ok.");
}
以上例子是输出与标准答案相差不超过0.1则AC。
注意事项:
- 头文件必须导入testlib.h,你没有也没关系,要保证不会出现编译错误
- testlib似乎包含了math,可以不导入math,但是其他的头文件要导入,不知道哪个有哪个没用,要是没有也会编译错误
语法:
- registerTestlibCmd:开头必须写,初始化
- quitf:有_ok和_wa,_ok就是AC,_wa就是WA,如果到return也没用调用就是UKE,第2个值写反馈信息,反馈的写法和printf一样
- quitp:与quitf的区别是,第一个值是可以让分数乘第一个值,一般小于1,0.5就是拿一半分
- ans:答案,就是读各个测试点
.out
里面写的东西
- ouf:用户输出
- inf:一般不需要,读各个测试点
.in
里面写的东西,除非规定特例,用不到
- setName:设置SPJ的名字,没啥用
ans、ouf、inf的成员函数;
- readChar():读一个字符,是ans、ouf、inf的成员函数
- readChar©:读一个字符,只能读变量c里的字符(直接一个单引号传也可以)
- readToken():读一个字符串,不是一行输入
- readString():读一行字符串
- readLine():同上
- readLong():读一个longlong或int64
- readLong(l,r):同上但规定范围(包括l和r)
- readInt():读一个int
- readInt(l,r):同上但规定范围
- readDouble():读一个double
- readReal():读一个实数
- readReal(l,r):读一个实数但规定范围
- readStrictReal(l,r,lp,rp):读一个实数,规定范围又规定精度
- readEoln():读一个换行,没有返回值
- readSpace():读一个空格,返回值char,相当于readChar(’ ')
- readEof():读一个eof
是可以测试的,前提是你把Testlib头文件下载了。
windows系统要输入:
checker.exe in.txt out.txt ans.txt
Linux系统要输入:
./checker in.txt out.txt ans.txt
in.txt out.txt ans.txt分别是输入输出和正确答案,这个只是测试用,不要一起打包。
交互库
交互库必须叫interactive_lib.cpp
,要带上交互题标签。
交互库实际上就是让用户把没有写完的函数写完。
例:
#include<iostream>
using namespace std;
extern "C"{
extern int jc(int x){
return jc(x-1)*x;
}
extern int solution(int a,int b,int c);
}
int main(){
int a,b,c;
cin>>a>>b>>c;
cout<<solution(a,b,c)<<endl;
return 0;
}
除了main以外函数名字随便改,只有main在外面其他都在extern里面。
除了一个要用户自己写的函数外,可以为用户定义一个函数,当然不定义也可以,定义了用户就可以直接使用写好的函数,不用自己写了。
比如例子就是solution
要用户写,jc
是提供给用户的函数。
如果题目要 ( a ! + b ! ) c (a!+b!)^c (a!+b!)c 的值,用户应该这样写:
#include<cmath>//交互库没有导入这个头文件,要导入一遍
extern "C" int jc(int);//要把给的函数先定义一遍
extern "C" int solution(int a,int b,int c){
return pow(jc(a)+jc(b),c);//return
}
用户不需要写main函数,也不应该写。
后记
实际上交互库可以和SPJ连接,不过我不会,可以去看洛谷,不过我估计你看不懂:)
t
h
a
n
k
s
f
o
r
w
a
t
c
h
!
\color{green}thanks~for~watch!
thanks for watch!
t
h
a
n
k
s
f
o
r
w
a
t
c
h
!
\color{blue}thanks~for~watch!
thanks for watch!
t
h
a
n
k
s
f
o
r
w
a
t
c
h
!
\color{red}thanks~for~watch!
thanks for watch!
t
h
a
n
k
s
f
o
r
w
a
t
c
h
!
\color{yellow}thanks~for~watch!
thanks for watch!
awa