浅谈spj
SPJ(special judge)是个好玩的东西,毕竟各类神奇的题目SPJ经常作为救火工具(比如说一不小心出成验证类的题目)。
但SPJ是个坑,毕竟只让用个“testlib.h”,输入还特别奇怪。今天我就带大家来玩一玩这个奇怪的东西
写在前面:
本来已经退役了暂时不打算补坑,但今天遇上了静静(我们教练)让我教她SPJ,于是索性把这篇文章的坑补完
一、明确内容
SPJ总体上主要分两大类:精度判断(lemon上叫实数比较)和方案验证。这两个东西其实思路完全不是一码事。
不过由于都是基于SPJ比较的大框架,所以都被归入SPJ。在开动之前我们必须明确你到底要写哪个,不然可能绕来绕去费上老半天劲儿还得返工。
二、操作简介(以下内容部分来自luogu的SPJ帮助,但是有部分修改,请小心食用)
1.读入部分
void registerTestlibCmd(argc, argv)
初始化checker,必须在最前面调用一次。
char a=readChar()
读入一个char,指针后移一位。
char a=readChar(char c)
和上面一样,但是只能读到一个字母c
char a=readSpace()
同 readChar(' ').
string a=readToken()
读入一个字符串,但是遇到空格、换行、eof为止、
long long a=readLong()
读入一个longlong/int64
long long a=readLong(long long L, long long R)
同上,但是限定范围(包括L,R)
int a=readInt()
读入一个int
int a=readInt(int L, int R),
同上,但是限定范围(包括L,R)`
double a=readReal()
读入一个实数
double a=readReal(double L, double R),
同上,但是限定范围(包括L,R)
double a=readStrictReal(double L, double R, int minPrecision, int maxPrecision),
读入一个限定范围精度位数的实数。
string a=readString(),
string a=readLine()
读入一行string,到换行或者eof为止
void readEoln()
读入一个换行符
void readEof()
读入一个eof
int a=eof()
2.输出部分
给出AC
quitf(\_ok, "The answer is correct. answer is %d", ans);
给出WA
quitf(\_wa, "The answer is wrong: expected = %f, found = %f", jans, pans);
给出PC(Partially Correct),并且可以获得该点50%的分数
quitp(0.5,"Partially Correct get %d percent", );
步骤分解:
关于输入:
输入部分没有什么好强调的,写过快读的同学都知道正确的写法。定义一个变量等于输入函数返回的值即可。
但需要注意的是,SPJ不是一个普通的C++程序,他使用的库是
#include“testlib.h”
所以,C++的很多操作在SPJ里是不能使用的。典型代表就是输入输出。你能且仅能使用上面提供的的读入方式。"cin",“printf”之类的东西都会让你CE
关于输出:
一句话说不清,各位请看下图
AC版
引号里的内容等价于上图的黑底白字部分
WA版
PC版(这个与上面的稍有不同)
三、实例分析
精度判断
精度判断相对于后者很简单,因为精度判断其实基本与常规评测模式并无差异。我们通常只需要判断选手答案与正确答案的差异是否在精度范围内。
所以使用SPJ的方式读入标准答案文件与选手输出文件,进行进度比较即可。
实战样例:
这道题的SPJ属于典型的精度比较类
因为保留一位小数,所以存在向下,向上,四舍五入等多种保留方式(题目中并没有规定)
所以我们考虑规定误差为0.1,直接误差比较即可
实例代码:
#include"testlib.h"//专属头文件不可少
using namespace std;
#define rii register int i
double eps=0.1;
int n,m;
int main(int argc,char *argv[])//流文件操作莫忘掉
{
registerTestlibCmd(argc,argv);//初始化checker要记牢
n=inf.readInt();
m=inf.readInt();
for(rii=;i<=m;i++)
{
double a1=ans.readDouble();
double a2=ouf.readDouble();
if(abs(a1-a2)>eps)//貌似cmath库直接集成,不需要自己写
{
quitf(_wa,"wrong answer on line %d",i);//给出错误结果
}
}
quitf(_ok,"correct answer");//给出正确结果
return ;
}
这是一个典型的验证类SPJ
给定一个方案,让你检验是否能达到要求的目的
两类操作:
(a) 将最后一个数移到最前面
(b) 把第三个数移到最前面
对于每个操作,我们简单的写一个双向链表维护即可
然后对于完成所有操作的序列,我们需要进行一次比较
判断得出的序列与给定的标准序列是否相同
然后按位比较即可
具体操作详见代码中的注释(以码风为界,分别为我和苏卿念写的【哪个是谁靠自己猜吧】)
#include "testlib.h"
#include <ctime>
using namespace std;
struct lb{
int pre,nxt,val;
}x[];
int n,cnt,head,tail;
void ltof(int num)//一号双向链表操作,把末尾的元素移到头部
{
while(num--)
{
int ls=x[tail].pre;
x[ls].nxt=;
x[tail].nxt=head;
x[tail].pre=;
x[head].pre=tail;
head=tail;
tail=ls;
}
}
void ttof(int num)//二号双向链表操作:第三个移到第一个
{
while(num--)
{
int cnt=;
int ls=head;
for(int i=;i<=;i++)
{
ls=x[ls].nxt;
}
int forth=x[ls].nxt;
int kkk=x[ls].pre;
x[forth].pre=kkk;
x[kkk].nxt=x[ls].nxt;
x[ls].pre=;
x[ls].nxt=head;
x[head].pre=ls;
head=ls;
}
}
void change(int num,int cz){//此函数用于判断操作
if(cz==) ltof(num);
else ttof(num);
}
char opt;int now;
char pos;
int m;
int main(int argc,char *argv[]) {//真正的spj主程序开始了
registerTestlibCmd(argc,argv);、、初始化输入
n=inf.readInt();
for(int i=;i<=n;i++) x[i].val=inf.readInt(),x[i].pre=i-,x[i].nxt=i+;//输入原始序列,并构造链表
head=,tail=n;int qnt=;
opt=ans.readChar();//读入操作类型
if(opt=='N') {//判断操作类型
pos=ouf.readChar();//读入操作数
if(pos!='N') quitf(_wa,"expect NIE found %c.score:pqp",pos);
pos=ouf.readChar();
if(pos!='I') quitf(_wa,"expect IE found %c.score:pqp",pos);
pos=ouf.readChar();
if(pos!='E') quitf(_wa,"expect E found %c.score:pqp",pos);
pos=ouf.readChar();
if(pos=='\n'||pos==||pos==) quitf(_ok,"the answer ios corect .score:qaq");
if(pos!=' ') quitf(_wa,"expect found %c.score:pqp",pos);
pos=ouf.readChar();
if(pos!='D') quitf(_wa,"expect DA found %c.score:pqp",pos);
pos=ouf.readChar();
if(pos!='A') quitf(_wa,"expect A found %c.score:pqp",pos);
pos=ouf.readChar();
if(pos!=' ') quitf(_wa,"expect found %c.score:pqp",pos);
pos=ouf.readChar();
if(pos!='S') quitf(_wa,"expect SIE found %c.score:pqp",pos);
pos=ouf.readChar();
if(pos!='I') quitf(_wa,"expect IE found %c.score:pqp",pos);
pos=ouf.readChar();
if(pos!='E') quitf(_wa,"expect E found %c.score:pqp",pos);
quitf(_ok,"the answer ios corect .score:qaq");
}
m=ouf.readInt(); if(n==&&m==) {quitf(_ok,"correct answer");return ;}
else if(n==) {quitf(_wa,"wrong answer");return ;}
for(int i=;i<=m;i++){
pos=;now=;
pos=ouf.readChar();
while(pos>''||pos<'') pos=ouf.readChar();
while(pos<=''&&pos>='') now=now*+pos-'',pos=ouf.readChar();
if(now<=||now>n) quitf(_wa,"wrong output on operation %d,found %d,expect in [ 1 , %d ] .score:vov",i,now,n);
if(pos=='b') now%=;
if(pos=='a') now%=n;
change(now,pos=='b'); }
int wz=head;
while(wz!=tail){
int nxt=x[wz].nxt;
if(x[nxt].val<x[wz].val){
quitf(_wa,"wrong answer");
return ;
}
wz=nxt;
}
if(x[x[tail].pre].val>x[tail].val) quitf(_wa,"worong answer ");
else quitf(_ok,"correct answer ");
return ;
}
未完待续……
浅谈spj的更多相关文章
- 浅谈 Fragment 生命周期
版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...
- 浅谈 LayoutInflater
浅谈 LayoutInflater 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/View 文中如有纰漏,欢迎大家留言指出. 在 Android 的 ...
- 浅谈Java的throw与throws
转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...
- 浅谈SQL注入风险 - 一个Login拿下Server
前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...
- 浅谈WebService的版本兼容性设计
在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...
- 浅谈angular2+ionic2
浅谈angular2+ionic2 前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别. 1. 项目所用:angular2+ionic2 ...
- iOS开发之浅谈MVVM的架构设计与团队协作
今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...
- Linux特殊符号浅谈
Linux特殊字符浅谈 我们经常跟键盘上面那些特殊符号比如(?.!.~...)打交道,其实在Linux有其独特的含义,大致可以分为三类:Linux特殊符号.通配符.正则表达式. Linux特殊符号又可 ...
- 浅谈Angular的 $q, defer, promise
浅谈Angular的 $q, defer, promise 时间 2016-01-13 00:28:00 博客园-原创精华区 原文 http://www.cnblogs.com/big-snow/ ...
随机推荐
- html5 移动端开发
移动端开发总结 目录 1.手机与浏览器 2.Viewport(视窗) 3. 媒体查询 4.px,em,rem,pt 5.设备像素比devicePixelRatio 6.移动web中的图标及字体 ...
- Android ListView实现新闻客户端的新闻内容图文混排
布局文件: <LinearLayout xmlns:android="<a href="http://schemas.android.com/apk/res/andro ...
- centos7安装go语言环境
安装包下载地址为:https://golang.org/dl/. 各个系统对应的包名: 解压安装 1.下载源码包:go1.7rc3.linux-amd64.tar.gz 2.将下载的源码包解压至 /u ...
- GitHub初步探索-1-使用本地代码管理工具,简化上传的过程
使用GitHub对于我们写Java的同志们来说是一个非常好的代码存储的方式,但是因为是全英文的,操作起来有一点复杂,所以我不是经常使用 ,但是最近代码越敲越多,再加上老师要求,希望使用比较简单的方法来 ...
- C#des加密算法指定键的大小对于此算法无效
api接口调用的时候,需要和java的进行加密通信,通信过程中用到DES加密,java那边DES的key为64位字符串,而之前c#的DES加密是key为8位 DESCryptoServiceProvi ...
- linux 下的python的最佳打开方式, you know?
IPython install IPython是Python的交互式Shell,提供了代码自动补完,自动缩进,高亮显示,执行Shell命令等非常有用的特性.特别是它的代码补完功能,例如:在输入zlib ...
- HTML后续
列表标签 <ul>.<ol>.<dl> 列表标签 无序列表 属性: type="属性值".属性值可以选: disc(实心原点,默认),squar ...
- iOS设计模式 - 适配器
iOS设计模式 - 适配器 效果 说明 1. 为了让客户端尽可能的通用,我们使用适配器模式来隔离客户端与外部参数的联系,只让客户端与适配器通信. 2. 本教程实现了适配器模式的类适配器与对象适配器两种 ...
- 火狐浏览器对svg支持的一点不足
项目中要用svg实现一个如下图所示的风机扇叶转动效果 当用chrome浏览器打开,动画显示正常.用火狐浏览器打开扇叶静止不动,代码如下: <svg xmlns:cge="http:// ...
- 3星|《深度思考:不断逼近问题的本质》:香奈儿前CEO自传
深度思考:不断逼近问题的本质 作者是前香奈儿CEO,主要内容是作者的自传,从家庭说起,一直到卸任香奈儿CEO. 作者出生于上世纪六七十年代的一个美国中西部的犹太家庭,崇尚自由,讨厌标签.高中的一个暑假 ...