算法競賽中提交答案題、交互題、通信題簡介和答題方法
提交答案題
簡介
提交答案題不需要你提交源代碼,只需要提交答案文件。
這類題目一般會先把輸入數據打包到下發文件里給你,交題的時候按照題目要求進行命名並放(提交)到指定位置。
答題方法
一般來講可能比較人類智慧,應該會給手玩的分數,可以手玩出幾組然后其他的寫程序跑或找規律等等。
注意這種情況下寫程序不需要執着在一秒或五秒內得到結果,事實上只要能在考試結束前得到答案都是可接受的。
例子
交互題
簡介
交互題,顧名思義,要求你的程序與命題人的程序(通常稱為交互庫)進行互動,來解決問題。
一般交互題的命題意圖:(僅為個人經驗,供參考)
- 解決實際問題。你不能獲得所有的信息,只能通過若干個給出的接口向交互庫提出問題,來得到你需要的答案。
- 強制在線。強制在線一般有兩種方式,對輸入數據進行加密(常為異或上次答案),或者進行交互。交互題的特點決定了你每次只能獲取一次詢問,並返回答案,才能獲取下一次詢問。
- 國外信息學競賽(例如 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 式交互例子
通信題
這個我還沒咋見過,先不寫了。