学习笔记:浅谈交互题
交互题
引入(瞎写的)
交互题交互题,顾名思义,你需要用电脑与官方机器交流,从而得出一些东西。这一类题目,往往限制你交流(或询问)的次数,让你猜出一个东西来。正因为测评程序可能对选手的询问作出限制,或调整应答策略来尽可能增加询问次数,这也给题目带来了更多变化。这是一类十分新颖的题,下面有几个比较经典的技巧:
- 二分答案
- 随机化
事实上,这一种题目与传统型题也并没有差多少,还是考验数学能力,甚至图论能力等。比赛中遇到了,往往难度不会小,甚至出现全场爆0 00的惨状。
学这个主要是因为洛谷月赛中有一道交互题,然而本人实力太菜不会写,遂学之。
再次深深感到自己的弱小……
做法
交互方式主要有如下两种。虽然技术上有不小的差异,但在考察算法的本质上它们并没有实际区别。
stdio 交互
stdio 交互(标准 I/O 交互)是 Codeforces、AtCoder 等在线平台的交互手段,也是 ICPC 系列赛事中的标准。对于这类题目,选手只需像往常一样将询问写到标准输出,刷新输出缓冲后从标准输入读取结果。选手程序刷新输出缓冲后,通过管道连接它的测评程序(称为交互器)才能立刻接收到这些数据。在 C/C++ 中, fflush(stdout) 和 std :: cout << std :: flush 可以实现这个操作(使用 std :: cout << std :: endl 换行时也会自动刷新缓冲区,但是 std :: cout << '\n' 不会);Pascal 则是 flush(output) 。
garder 交互
grader 交互方式常见于 IOI、APIO 等国际 OI 赛事(特别是 CMS 平台的竞赛)。
对于这类题目,选手只需编写一个特定的函数完成某项任务,它通过调用给定的若干辅助函数来进行交互。
为了便于选手在本地测试,题目会下发一个头文件与一个参考测评程序 grader.cpp(对于 Pascal 语言是一个库 graderlib),选手将自己的程序与 grader.cpp 一同编译方可得到可执行文件:
g++ grader.cpp sol.cpp -o a -Wall -O2 -lm -std=c++14 -static
编译得到的程序表现与传统题程序类似。它会打开固定的文件,以固定的格式读取数据,调用选手编写的函数,并将结果和若干信息(例如询问的次数、答案正确性)显示在标准输出上。
实际测评时,选手的程序会与一个不同的 grader.cpp 编译。这个 grader.cpp 将以类似的方式调用选手编写的函数,并记录其得分。一般来说,这个版本的 grader.cpp 所有全局符号都会设为 static,也即不能通过冲突命名的方式破解它,但是任何尝试突破 grader 限制的行为都会被判失格 (disqualification)。
stdio 交互与 grader 交互的差别
stdio 交互的一个明显优势在于它可以支持任何编程语言,但是输入输出的耗时容易成为问题设计的瓶颈,导致有时无法区分程序的时间效率差别;grader 交互则恰好相反,由于函数调用的开销不大,常常可以允许 $10^6$ 数量级的询问次数,但是语言的限制是其短板。
如果自己设计题目或举办比赛,需要对二者认真权衡和比较。
交互题怎么进行本地测试
唔……好问题。交互式的题一般给了一个头文件要你 include 进来,以及一个实现接口的源文件 grader。好像大家对多个源文件一起编译还不太熟悉。
对于C++:g++ -o code grader.cpp code.cpp
对于C语言:gcc -o code grader.c code.c
如果你是悲催的电脑盲,实在不会折腾没关系!你可以把 grader 的文件内容完整地粘贴到你的 code 的 include 语句之后,就可以了!
什么你是萌萌哒 Pascal 选手?一般来说都会给个 grader,你需要写一个 Pascal 单元。这个 grader 会使用你的单元。所以你只需要把源文件取名为单元名 + .pas,然后:
对于Pascal语言:fpc grader.pas
就可以啦!

浙公网安备 33010602011771号