Description
A site built with vuepress-theme-hope
普通模式是程序在线评测平台(OJ)通用的判题模式,主要的实现逻辑步骤如下:
Tips
选手程序读取题目标准输入文件的数据
判题机执行代码逻辑得到选手输出
再将选手输出与题目标准输出文件的数据进行对比,最终得到判题结果
特殊判题(Special Judge)是指OJ将使用一个特定的程序来判断提交的程序的输出是不是正确的,而不是单纯地看提交的程序的输出是否和标准输出一模一样。
一般使用Special Judge都是因为题目的答案不唯一,更具体一点说的话一般是两种情况:
Tips
HOJ支持testlib.h头文件的直接使用 具体使用文档请看https://oi-wiki.org/tools/testlib/ (opens new window)
在创建题目的适合,选择开启特殊判题,编写特殊判题程序,然后编译通过便可。
后台对题目使用特殊判题时,请参考以下程序例子 判断精度
#include <iostream>
#include "testlib.h"
using namespace std;
int main(int argc, char *args[]){
/**
inf: 输入文件流
ouf: 选手输出流
ans: 标准答案流
**/
registerTestlibCmd(argc, args);
double pans = ouf.readDouble();
double jans = ans.readDouble();
if (fabs(pans - jans)<0.01)
quitf(_ok, "The answer is correct.");
else
quitf(_wa, "The answer is wrong: expected = %f, found = %f", jans, pans);
// quitf(_pe, "The answer is presentation error."); // 格式错误
// quitf(_fail, "The something wrong cause system error."); // 系统错误
}
#include<iostream>
#include<cstdio>
#define PC 99 // 部分正确
#define AC 100 // 全部正确
#define PE 101 // 格式错误
#define WA 102 // 答案错误
#define ERROR 103 // 系统错误
using namespace std;
void close_file(FILE *f){
if(f != NULL){
fclose(f);
}
}
int main(int argc, char *args[]){
/**
args[1]:标准输入文件路径
args[2]:选手输出文件路径
args[3]:标准输出文件路径
**/
FILE *std_input_file = fopen(args[1], "r");
FILE *user_output_file = fopen(args[2], "r");
FILE *std_output_file = fopen(args[3], "r");
double std_out; // 标准输出
fscanf(std_output_file, "%lf", &std_out);
double user_output;// 用户输出
fscanf(user_output_file, "%lf", &user_output);
// 关闭文件流
close_file(std_input_file);
close_file(user_output_file);
close_file(std_output_file);
if (fabs(user_output - std_out)<=1e-6)
return AC;
else
// fprintf(stderr, "这里会输出错误提示");
// fprintf(stderr, "%s","这里会输出错误提示");
return WA;
}
如果是OI题目,需要该测试点部分得分,则可参考如下
#include<iostream>
#include<cstdio>
#define PC 99 // 部分正确
#define AC 100 // 全部正确
#define PE 101 // 格式错误
#define WA 102 // 答案错误
#define ERROR 103 // 系统错误
using namespace std;
void close_file(FILE *f){
if(f != NULL){
fclose(f);
}
}
int main(int argc, char *args[]){
/**
args[1]:标准输入文件路径
args[2]:选手输出文件路径
args[3]:标准输出文件路径
**/
FILE *std_input_file = fopen(args[1], "r");
FILE *user_output_file = fopen(args[2], "r");
FILE *std_output_file = fopen(args[3], "r");
double std_out; // 标准输出
fscanf(std_output_file, "%lf", &std_out);
double user_output;// 用户输出
fscanf(user_output_file, "%lf", &user_output);
// 关闭文件流
close_file(std_input_file);
close_file(user_output_file);
close_file(std_output_file);
if(...){ // 符合部分得分
fprintf(stdout, "%lf", 50.0); // 表示获得该测试点50.0%的分数
fprintf(stderr, "这里会输出错误提示");
return PC;
}
}
交互题 是需要选手程序与测评程序交互来完成任务的题目。一类常见的情形是,选手程序向测评程序发出询问,并得到其反馈。
交互方式主要有如两种:STDIO 交互和Grader 交互
Tips
主要的交互逻辑:交互程序的标准输出通过交互通道写到选手程序标准输入,选手程序的标准输出通过交互通道写到交互程序的标准输入,两者需要刷新输出缓存
Note
在 C/C++ 中,fflush(stdout)
和 std::cout << std::flush
可以实现这个操作(使用 std::cout << std::endl
换行时也会自动刷新缓冲区,但是 std::cout << '\n'
不会)
A+B问题
选手程序
#include <iostream>
#include <cstdio>
using namespace std;
int main(){
int a,b;
cin >> a >> b;
cout << a + b;
return 0;
}
交互程序(这里使用testlib来实现,但也可以自己读取文件实现)
#include "testlib.h"
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
setName("Interactor A+B");
registerInteraction(argc, argv);
// 读取题目标准输入文件的数据
int a = inf.readInt();
int b = inf.readInt();
// 往交互通道写数据,记得用endl刷新缓冲区
cout << a << " " << b << endl;
int ans;
// 读取用户程序写入到交互通道的数据
cin >> ans;
if (a + b == ans){ // 判断结果
quitf(_ok, "correct");
}else{
quitf(_wa,"incorrect");
}
}
Info
主要的交互逻辑:
需要给选手的程序添加交互库,在后台的题目管理可以选择添加。
交互库:提供写好的方法给选手调用
#include <bits/stdc++.h>
using namespace std;
namespace interactive {
static int n, m, cnt;
static bool hasUsedGetN = false;
static bool hasSubmitted = false;
void RE() {
puts("re");
exit(0);
}
int getn() {
if (hasUsedGetN) RE();
cin >> n;
hasUsedGetN = 1;
m = rand() % n + 1;
return n;
}
int query(int x) {
if (!hasUsedGetN || hasSubmitted) RE();
cnt++;
if (cnt > 100000) RE();
if (x == m)
return (rand() % 10 <= 3);
else
return (rand() % 10 <= 4);
}
void submit(int x) {
if (hasSubmitted) RE();
if (x == m)
puts("ok");
else
puts("wa");
hasSubmitted = 1;
}
}
using interactive::getn;
using interactive::query;
using interactive::submit;
用户程序:调用库文件的方法进行答题
#include <bits/stdc++.h>
#include "interactive.h"
int main()
{
int n = getn();
for(int i = 1; i <= n; i++)
{
for(int j = 0; j < 900; j++)
{
if(query(i)) arr[i]++;
}
}
int min = 1000, ans = 0;
for(int i = 1; i <= n; i++)
{
if(arr[i] < min)
{
min = arr[i];
ans = i;
}
}
submit(ans);
return 0;
}
交互测评程序:根据选手调用交互库执行逻辑后得出的结果,来进行最终判断评测的结果
#include "testlib.h"
#include <string>
int main(int argc, char* argv[]) {
registerTestlibCmd(argc, argv);
// 读取选手最终输出文件的数据来判断结果
std::string s = ouf.readToken();
if (s == "ok")
quitf(_ok, "Correct");
else
quitf(_wa, "Wrong Answer");
}
This app can be installed on your PC or mobile device. This will allow this web app to look and behave like any other installed app. You will find it in your app lists and be able to pin it to your home screen, start menus or task bars. This installed web app will also be able to safely interact with other apps and your operating system.
A site built with vuepress-theme-hope