果光的评测姬
Problem:B
Time Limit:1000ms
Memory Limit:65535K
Description
蒟蒻果光在寒假训练中被NEFU的评测姬折磨的快疯了,于是果光想到了一个疯狂的报复方法,那就是写一个评测姬评测一下别人的程序寻找快感。
既然评测姬是自己人嘛,肯定要留个后门啦,如果是果光自己的程序(用户名为"guoguang"),无论程序运行结果如何,都要返回AC,至于别人的程序嘛,当然是正常进行评测了。
由于果光太菜了,虽然他想到了这个激动人心的好方法,但是他却不会写这个评测程序。现在已知标程的输出结果和多个用户的输出结果,请你根据这些信息对用户的程序进行评测。
评测遵循以下规则:
1、若用户程序输出与标准程序输出完全相同或用户程序测试点尾部仅比标准程序多输出一个换行符,判定为 AC。
2、若用户信息(含义见输入)中不包含任何测试点,判定为 CE。
3、若用户信息中存在测试点,但什么都没有输出,判定为 RE。
4、若用户程序每个测试点输出的内容除去空格和换行符外均与标准程序输出的相同,判定为 PE。
5、若用户程序输出超过5000个字符(>5000 包括空格和换行符),判定为 OLE。
6、其他情况均判定为 WA,输出的同时需要输出第一个 WA 的测试点。
Input
单组输入。
输入开头是标准程序输出的 n 个测试点,每个测试点在单独一行的 “CASE_BEGIN” 和 "END_OF_CASE"之间。
下面是 m 个用户信息。
每个用户信息由用户名和测试点输出组成,第一行是 "USER " 和对应的用户名,接下来是用户的 n 个测试点输出,在 “CASE_BEGIN” “END_OF_CASE” 之间。
注:如果用户程序 CE,用户信息中将不包含测试点信息。
数据范围:用户名长度不超过 20 个字符,测试点数量不超过10个,每个测试点不超过 5000 个字符,测试点每行不超过 1000 个字符(包括行尾换行符),用户数量不超过 20 个。
Output
每个用户输出两行,每两个用户之间用一个空行隔开(整个输出以一个空行结尾)。
第一行输出 “USER username” username为对应用户的用户名。
第二行输出评测结果,结果有以下几种情况:
直接输出以下错误信息:“Accepted” “Presentation Error” “Compile Error” “Runtime Error” “Output Limit Exceeded”
当错误为 “Wrong Answer” 时,需要额外输出第一个 WA 测试点的编号,例如 “Wrong Answer at Case #0”
注:当遇到 PE 以外错误时评测姬应停止评测该用户的程序,自动忽略剩余测试点的结果。
Sample Input
样例1输入:
CASE_BEGIN
123 456
END_OF_CASE
USER guoguang
CASE_BEGIN
hiahiahia 😃
END_OF_CASE
USER dalao
CASE_BEGIN
123456
END_OF_CASE
USER caijiguoguang
USER jvruoguoguang
CASE_BEGIN
END_OF_CASE
USER wtcl
CASE_BEGIN
wtcl
END_OF_CASE
样例2输入:
CASE_BEGIN
123
END_OF_CASE
CASE_BEGIN
456
END_OF_CASE
USER user
CASE_BEGIN
123
END_OF_CASE
CASE_BEGIN
456
END_OF_CASE
Sample Output
样例1输出:
USER guoguang
Accepted
USER dalao
Presentation Error
USER caijiguoguang
Compile Error
USER jvruoguoguang
Runtime Error
USER wtcl
Wrong Answer at Case #0
样例2输出:
USER user
Accepted
/果光的评测姬 By Guoguang
#include <bits/stdc++.h>
using namespace std;
char cases[11][5001]={0};
char thiscase[5001]={0};
int rc=0,cnum=0,sampleok=0,res,ucnum=0;
char line[1001],status={0};
void readtoEOC() //读取到测试点结束
{
while(gets(line))if(!strcmp(line,"END_OF_CASE"))break;
}
int readTestCase(char readBuf[]) //读取一个测试点到readBuf中
{
memset(readBuf,0,sizeof(readBuf));
int ole=0;
while(gets(line)!=NULL)
{
if(!strcmp(line,"END_OF_CASE")) //读取到测试点尾
{
readBuf[strlen(readBuf)-1]=0; //结尾补\0
if(ole)return 0; //判断是否ole
else return 1;
}
if(!ole) //没有ole就继续读
{
if(strlen(readBuf)+strlen(line)>5000) //ole了
{
ole=1;
continue;
}
line[strlen(line)+1]=0; //补\0
line[strlen(line)]='\n'; //加换行
strcat(readBuf,line); //读到的这行加到readBuf里
}
}
}
int judge(char sampleop[],char userop[]) //评测 标准输出与用户输出
{
int lens=strlen(sampleop);
int lenu=strlen(userop);
if(!lenu)return 2; //没输出返回RE
if(!strcmp(sampleop,userop))return 0; //完全相同返回AC
if(lenu-lens==1&&userop[lenu-1]=='\n') //用户比标准输出多个换行
{
userop[lenu-1]=0; //去掉多的换行进行比较
lenu--;
if(!strcmp(sampleop,userop))return 0; //返回AC
}
int sp=0,up=0;
while(1)
{
while(up+1<lenu&&(userop[up]=='\n'||userop[up]==' '))up++; //忽略用户输出换行和回车
while(sp+1<lens&&(sampleop[sp]=='\n'||sampleop[sp]==' '))sp++; //忽略标准输出换行和回车
if(userop[up]!=sampleop[sp])return 4; //逐字符比较,不同返回WA
sp++;up++; //比较下一字符
if(up==lenu&&sp==lens)return 3; //同时结束返回PE
else if(up+1==lenu&&sp+1==lens) //只剩最后一个字符
{
if((sampleop[sp]=='\n'||sampleop[sp]==' ')&&(userop[up]=='\n'||userop[up]==' ')||userop[up]==sampleop[sp])return 3;
else return 4;
}
else if(up==lenu) //用户输出先结束
{
while(sp+1<lens&&(sampleop[sp]=='\n'||sampleop[sp]==' '))sp++;
if(sp+1==lens&&(sampleop[sp]=='\n'||sampleop[sp]==' '))return 3;
else return 4;
}
else if(sp==lens) //标准输出先结束
{
while(up+1<lenu&&(userop[up]=='\n'||userop[up]==' '))up++;
if(up+1==lenu&&(userop[up]=='\n'||userop[up]==' '))return 3;
else return 4;
}
}
}
void printans(int sta,char user[],int caseno) //输出答案
{
printf("USER %s\n",user);
switch(sta)
{
case 0:
printf("Accepted\n");
break;
case 1:
printf("Output Limit Exceeded\n");
break;
case 2:
printf("Runtime Error\n");
break;
case 3:
printf("Presentation Error\n");
break;
case 4:
printf("Wrong Answer at Case #%d\n",caseno);
break;
case 5:
printf("Compile Error\n",caseno);
break;
}
printf("\n");
}
int main()
{
char cuser[21]={0};
int csta,ccase,cskip;
while(~scanf("%s",line)) //默认读取行的第一个单词
{
if(!strcmp(line,"CASE_BEGIN")) //读取到测试点
{
if(sampleok) //已读入标准输出(应读取用户输出)
{
if(cskip) //已经停止对该用户的评测 (WA,RE,OLE时)
{
readtoEOC(); //跳过该测试点
continue;
}
res=readTestCase(thiscase); //读测试点,返回值0为OLE 1为正常
if(!res)
{
printans(1,cuser,ccase); //输出OLE
cskip=1; //跳过该用户后续测试点
continue;
}
res=judge(cases[ccase++],thiscase); //评测,返回值与printans中的sta相对应
if(res==2||res==4)printans(res,cuser,ccase-1),cskip=1; //出错跳过并输出答案
if(csta!=3)csta=res; //非PE时记录该用户评测状态
}
else
{
readTestCase(cases[cnum++]); //读取到标准输出
}
}
if(!strcmp(line,"USER")) //读取到用户
{
if(!cskip&&strlen(cuser)) //输出上一组用户结果
{
printans(csta,cuser,0);
}
scanf("%s",cuser); //读用户名
sampleok=1; //已完成标准输出的读取
ccase=0; //当前测试点
csta=5; //默认CE(无测试点)
cskip=0; //不跳过该用户的评测
if(!strcmp(cuser,"guoguang")) //给自己开后门
{
printans(0,cuser,0); //直接输出AC
cskip=1; //跳过评测阶段
}
}
}
if(!cskip&&strlen(cuser)) //输出最后一组答案
{
printans(csta,cuser,0);
}
return 0;
}