算法竞赛中提交答案题、交互题、通信题简介和答题方法(没写完)

算法竞赛中提交答案题、交互题、通信题简介和答题方法

提交答案题

简介

提交答案题不需要你提交源代码,只需要提交答案文件。

这类题目一般会先把输入数据打包到下发文件里给你,交题的时候按照题目要求进行命名并放(提交)到指定位置。

答题方法

一般来讲可能比较人类智慧,应该会给手玩的分数,可以手玩出几组然后其他的写程序跑或找规律等等。

注意这种情况下写程序不需要执着在一秒或五秒内得到结果,事实上只要能在考试结束前得到答案都是可接受的。

例子

洛谷 P1008 三连击

交互题

简介

交互题,顾名思义,要求你的程序与命题人的程序(通常称为交互库)进行互动,来解决问题。

一般交互题的命题意图:(仅为个人经验,供参考)

  • 解决实际问题。你不能获得所有的信息,只能通过若干个给出的接口向交互库提出问题,来得到你需要的答案。
  • 强制在线。强制在线一般有两种方式,对输入数据进行加密(常为异或上次答案),或者进行交互。交互题的特点决定了你每次只能获取一次询问,并返回答案,才能获取下一次询问。
  • 国外信息学竞赛(例如 APIO)的题目往往不用你实现整个程序,而是实现几个接口函数,这类题目与交互题类似。
  • 虽然这是道传统题,但我就是要出成交互,我爱交互!!1 ← 这种出题人……这题出的很好,下次别出了,祝 TA 身体健康。

一般交互题的形式有两种:

  • Grader 交互(函数式交互):给你提供几个函数接口,向交互库提问时调用;同时你需要实现几个函数接口,供评测时获取你的答案用。
  • I/O 式交互:通过标准输出流向交互库提问或给出答案,从标准输入流读入输入信息和提问的回答。

Grader 交互(函数式交互)

题目会给你一个必须包含的头文件和几个函数接口,你需要实现另外要求的函数接口。

一般来讲好的题目描述会通过如下方式给出:(仅为举例,不一定有实际意义)

  • 请在程序中包含 array.h 头文件。
  • 你可以调用一个函数 int compare(int x, int y),返回值为:若 \(x < y\),返回 \(-1\);若 \(x = y\),返回 \(0\);若 \(x > y\),返回 \(1\)(这个函数接口没啥意义,但是一个挺好的例子)。
  • 你需要实现一个函数 void init(vector<int> A, int n),接收输入数据。这个函数会在程序开始时被调用恰好一次。
  • 你需要实现一个函数 int find_minimum(int l, int r),返回值为 \(A\) 中下标在 \([l, r]\) 的数中最小数的值。这个函数会被调用不超过 \(q\) 次。

此时你可以实现下面一个程序:

#include "array.h"
#include <bits/stdc++.h>
using namespace std;

void init(vector<int> A, int n) {
    ; // 什么都不做
}
int find_minimum(int l, int r) {// 这么做是没有意义的,只是一个例子
    if(compare(l, r)) return 0; // 当区间长度大于 1 时,返回 0
    return 1;                   // 当区间只有一个数时,返回 1
}

注意你不需要,也不应当实现主函数。

在提交前仔细检查是否包含头文件、是否删掉了主函数。

Grader 交互(函数式交互)例子

洛谷 P1947 猜数 以及 [APIO 的所有题](https://www.luogu.com.cn/problem/list?tag=85&page=1&orderBy=pid&order=desc(但是洛谷好多 APIO 都被改成传统题了。。)。

请注意这个例子与实际比赛中 Grader 交互题的不同:因为洛谷交互题实现原因,这道题没有要求包含头文件,而实际比赛中往往需要。

I/O 式交互

这类交互在实际比赛中较少用到(除了 CodeForces 等线上平台的比赛),建议重点掌握 Grader 交互,当然以防万一这种也要会。

题目会给你你的询问方式,并给出你答题的方式。

举一个猜数的例子:

  • 首先你要读入一个整数 \(n\),表示待猜的数在 \([1, n]\) 中。
  • 你可以通过 ? x 的方式向交互库提问,随后读入一个整数表示回答。如果 \(x\) 小于待猜的数,交互库回答 \(-1\);如果 \(x\) 等于待猜的数,交互库回答 \(0\);如果 \(x\) 大于待猜的数,交互库回答 \(1\)
  • 当你猜出这个数后,你可以通过 ! x 给出答案,\(x\) 即为这个数。

注意 I/O 交互中你每次输出需要刷新输出缓冲区,对于 C/C++ 语言可以 fflush(stdout);,对于 C++ 语言可以 cout<<endl;

你可以实现这样的程序:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    scanf("%d", &n);
    for(int i=1;i<=n;i++) {
        printf("? %d\n", i);
        fflush(stdout);
        int x;
        scanf("%d", &x);
        if(!x) {
            printf("! %d\n", i);
            return 0;
        }
    }
    return 0;
}

当然这个程序会超时,只是作为例子我懒得写二分。

I/O 式交互例子

洛谷 P1733 猜数 以及 CF 上的大多数交互题

通信题

这个我还没咋见过,先不写了。

posted @ 2022-01-28 22:04  rui_er  阅读(1212)  评论(2编辑  收藏  举报