HydroOJ教程(教师版)
引言
杭四中 OJ 已部署在下沙校区综合楼 506 机房,内网 IP 为10.0.98.217:8888。本文是面向之前没有 OJ 使用经验的老师以及题目志愿者。本文将针对日常使用的常见情况进行动态更新
如何添加题目?
首先,要了解出一个题需要哪些东西:题面和数据。我们将针对这两部分进行分别讲解
题面
依次点击题库--创建题目:

然后能够看到这个页面:

在这个页面中依次填写题目 ID,标题,标签,难度,题面。题目 ID 一般用字母+数字的形式,通常的题目应该都是用户自出题,应该用 T 开头,也就是 T5,T6...(建议查看题库查询 T 开头题目最大编号,避免重复)。然后填写标题,标题可以用类似“【十月月赛】xxx”的形式,前面用一个方括号代表题目来源。标签和难度是可选的,对于选考班,建议难度都设置为 1(因为一般比较简单),标签一般只要写出题年份就行。题面的话一般是题目背景、题目描述、输入/输出格式,提示/说明。题面的输入使用 Markdown 格式,具体语法建议自行百度,此处不多赘述。在做完这一切后,可以按照用途选择是否隐藏:如果是比赛试题,建议隐藏;如果是练习题目,就不必要隐藏。隐藏后除了管理员以及部分题目志愿者外无权限进行查看,具体权限安排请联系 AndyShen2006 或 chala_tea。
完成这一切后点击创建,你就完成了这个题目的 50%。
数据
对于一个题目来说,另外一个重要组成部分就是数据。在进行完刚刚的那个步骤之后,会自动跳转的数据页面:

你可以点击上传上传数据。
数据一般我们使用数据包的形式进行上传,一个数据包是包含若干个数据点的 zip 压缩包(一个数据点由一个.in 文件和一个.out 文件组成,分别代表了输入和标准输出,当选手程序的代码在该输入下输出的内容与标准输出相同时,该数据点将被判断为 Accepted,如果所有数据点都 Accepted,那么这道题目就视为 AC,否则按照 Accepted 点的数目进行对应给分(OI/IOI 赛制,ACM 赛制该规则不适用))。
数据生成者要对输入内容的性质有非常准确的把握,简单说就是能够判断什么样的数据是合法的,接下来我举两个例子来说明这一点:
后缀表达式
对于一个合法的后缀表达式,应当符合任意前缀的数字数量>符号数量。这一点从模拟栈的角度看就非常清晰:你每当有一个符号会进行两次出栈一次入栈,该操作使栈长度-1,那么,如果当符号数量大于数字数量时,栈就会出现负长度,从而变的不合法。使用者一点,我们在生成数据时就应当注意:记录数字数量和符号数量,然后维护合法性:
以下为生成后缀表达式的 generator(C++编写,采用cdg 库):
#include <bits/stdc++.h>
#include <ext_random.hpp>
using namespace std;
int main()
{
int numN = randint(50, 100);
int opN = numN - 1;
int numCnt = 0, opCnt = 0;
cout << numN + opN << endl;
while (numN + opN > 0) {
if (numCnt > opCnt + 1) {
bool op = randint(0, 1);
if (op) {
cout << randint(1, 10) << endl;
numCnt++;
numN--;
} else {
int type = randint(0, 2);
switch (type) {
case 0:
cout << '+' << endl;
break;
case 1:
cout << '-' << endl;
break;
case 2:
cout << '*' << endl;
break;
default:
break;
}
opCnt++;
opN--;
}
} else {
cout << randint(1, 10) << endl;
numCnt++;
numN--;
}
}
return 0;
}DAG(有向无环图)
对于一个有向无环图,拥有单向性,也就是进行拓扑排序后的顺序是确定的。这一单向性,与自然数的有序性相符:故如果我们在数据生成时总是将小编号节点指向大编号节点,那么一定会得到一个 DAG 图。
这两个例子充分的说明了:生成数据对出题人个人能力有着比较高的要求:必须要充分掌握输入性质才能造出合法强大的数据。
对于 Python 用户,可以考虑使用洛谷团队开发的CYaRon,具体使用方法请参见文档,此处不赘述。同时,你也可以使用 Python 内部自带的 random 库当中的 randint 等函数,仍然能够解决很多问题。
完成数据生成器之后,你可以手动调用数据生成器,然后将输出的数据保存到一个 xxxN.in 当中(你可以使用重定向输出功能直接输出到文件,这也是对于大部分人比较推荐的做法)(对于使用手动拷贝的用户:注意,不要用 Windows 记事本,Windows 记事本默认采用 CRLF 且带有 BOM 记号,比较烦,建议使用 VSCode Sublime UltraEdit 等软件并注意采用换行模式为 LF)。然后将 xxxN.in 手动输入标准 std 或通过文件重定向到标准 std,得到答案,并且保存为 xxxN.out,这样你就得到了一个数据点(注意,xxx 为题目名字,N 为题目编号。名字可以没有,但是编号一定要从 1 开始到 n,且对于每个 in 文件必须要有对应的 out 文件,不然上传时会错误识别)。反复操作,得到若干组数据,然后压缩成 zip(不要用 rar),然后上传即可。
上传完成后,你就成功的完成了一道题目。