前言
最近我同學有在架設我們學校的線上評測系統,而一開始我們的系統非常不穩定,因此,他想到可以寫離線的程式答題系統緩解我們上課的需求。而我看到這個系統,我覺得這是一個不錯的想法,並依此加以改良,新增 TLE 判定和超時時會強制停止,並且可以跨平台使用。
使用(解題者)
一題會是一個資料夾,裡面會有隱藏檔案和非隱藏檔案。
檔案名稱 |
大致內容 |
是否隱藏 |
AC |
ascii art 的 AC 字樣 |
True |
WA |
ascii art 的 WA 字樣 |
True |
TLE |
ascii art 的 TLE 字樣 |
True |
main.h |
主要程式 |
原則上 True |
Run.cpp |
執行程式 |
False |
Solve.h |
使用者的程式 |
False |
Description |
題目敘述 |
False |
README.txt |
說明使用方法(如下) |
False |
README.txt 內文
以下說明檔案功能及用法
- 編譯並執行 Run.cpp 可以獲得評測結果
- 程式碼請寫在 Solve.h 裡面
- 題目敘述在 Description 裡面,一般應該是 .txt,.md 或 .pdf
- 標準輸入輸出用 cin 和 cout 就可以了
以下說明答題結果
- AC 作答正確
- WA 輸出結果錯誤,或不符合題目要求
- TLE 執行時間過長
- 程式跳掉 一般來說都是 RE(runtime error)
以下規定請勿違反
- 擅自更改除 Solve 以外的檔案
貼心小提醒
由於 Solve 函式會被重複使用,因此變數就算開在全域也要記得初始化
截圖
使用(出題者)
資料夾中還含有一個隱藏資料夾 TestCase,裡面存放有測試資料。裡面的檔案如下
檔案名稱 |
大致內容 |
Gen.cpp |
預設的測試資料生成程式 |
GraphGen.h |
圖論測資生成程式 ( 使用介紹 ) |
log.txt |
測試資料們的基本資料 |
OJ |
生成可以上傳到 UOJ 系統的測試資料 |
Gen.cpp
介紹各個函式的功能
函式 |
功能 |
RandomNumber(long long a,long long b) |
生成一個隨機數 ( 範圍[a,b] ) |
RandomNumber(long long n) |
生成一個隨機數 ( 範圍[1,n] ) |
solve() |
共用解答函式 ( 有需要的話 ) |
SubTesk1(int a) |
生成第 a 筆測資 |
如果覺得 RandomNumber 太長,GraphGen.h 裡面有相同功能的函式 Rand
其他都不是非常重要,主要是可以同時支援 UOJ 格式的測資。以下是 a+b problem 的範例。
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
| #include<bits/stdc++.h> #include "GraphGen.h" using namespace std;
unsigned seed=chrono::steady_clock::now().time_since_epoch().count(); mt19937_64 rng=mt19937_64(seed);
long long RandomNumber(long long a,long long b){ uniform_int_distribution<long long> dis(a,b); return dis(rng); }
long long RandomNumber(long long n){ return RandomNumber(1,n); }
void solve(){ ; }
void SubTesk1(int a){ string fileName=to_string(a);
ofstream ques(fileName+".in"),ans(fileName+".out");
int aa=RandomNumber(10000),b=RandomNumber(10000);
ques<<aa<<" "<<b<<"\n";
ans<<aa+b<<"\n";
cout<<a<<endl; }
void UOJ(int a){ string fileName="./OJ\\a"+to_string(a);
ofstream ques(fileName+".in"),ans(fileName+".out");
int aa=RandomNumber(10000),b=RandomNumber(10000);
ques<<aa<<" "<<b<<"\n";
ans<<aa+b<<"\n";
cout<<a<<endl; }
void ExTest(int a){ string fileName="./OJ\\ex_a"+to_string(a);
ofstream ques(fileName+".in"),ans(fileName+".out");
int aa=RandomNumber(10000),b=RandomNumber(10000);
ques<<aa<<" "<<b<<"\n";
ans<<aa+b<<"\n";
cout<<a<<endl; }
#define REP(i,a,b) for(int i=(a);i<(b);++i) int main(){ ios::sync_with_stdio(0);cin.tie(0);
clock_t startTime=clock();
REP(i,1,5+1){ SubTesk1(i); }
REP(i,1,10+1){ UOJ(i); }
REP(i,1,10+1){ ExTest(i); }
clock_t endTime=clock();
cout<<double(endTime-startTime)/1000<<"\n"; }
|
log.txt
只有兩行,第一行是測試資料數目,第二行是執行時間限制,以毫秒為單位。
1 2
| TestCases: 5 TimeLimit(ms): 50
|
主程式
函式 |
功能 |
RunCode(int timeLimit) |
執行使用者程式(會計算時間,盡量減少多餘程式碼) |
RunTestCase(int testCase,int timeLimit) |
完成執行第 testCase 筆測試資料所需的前置條件 |
Judge(int testCase) |
評判解答正確性 |
RunSolution() |
執行所有測試並輸出結果 |
code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
| #ifndef MAIN_H #define MAIN_H
#include<bits/stdc++.h> #include<conio.h> #include "Solve.h" using namespace std;
bool isfinish=false; vector<int> costTime;
class TimeLimitExceeded : public exception{ public : TimeLimitExceeded() : exception() {} };
void RunCode(int timeLimit){ isfinish=false; clock_t start=clock();
Solve();
isfinish=true;
clock_t end=clock();
if(end-start>timeLimit){ throw TimeLimitExceeded(); return; }
costTime.emplace_back(end-start); }
bool RunTestCase(int testCase,int timeLimit){ string fileNum=to_string(testCase);
string inputFile="./TestCase\\"; inputFile+=fileNum; inputFile+=".in";
string userOutput="./TestCase\\sol"; userOutput+=fileNum; userOutput+=".out";
freopen(inputFile.c_str(),"r",stdin); freopen(userOutput.c_str(),"w",stdout);
thread run{RunCode,timeLimit};
chrono::milliseconds s(timeLimit+20); this_thread::sleep_for(s);
if(!isfinish){ run.detach(); throw TimeLimitExceeded(); return false; }else{ run.join(); return true; } }
bool Judge(int testCase){ ifstream userOutput("./TestCase\\sol"+to_string(testCase)+".out"); ifstream question("./TestCase\\"+to_string(testCase)+".in"); ifstream answer("./TestCase\\"+to_string(testCase)+".out");
string tp,userAns,systemAns;
while(userOutput>>tp){ userAns+=tp; if(userAns.size()>10000000){ return false; } }
while(answer>>tp){ systemAns+=tp; }
cerr<<" "; return systemAns==userAns; }
void RunSolution(){ ifstream log("./TestCase\\log.txt");
string recycle; int testCases,timeLimit;
log>>recycle>>testCases; log>>recycle>>timeLimit;
cerr<<"There're "<<testCases<<" testcases."<<"\n"; cerr<<"Running TestCase..."<<"\n";
try{ for(int i=1;i<=testCases;++i){ RunTestCase(i,timeLimit); cerr<<i<<" "; } cerr<<"\n\n"; }catch(TimeLimitExceeded){ ifstream TLE("TLE"); string line; while(getline(TLE,line)){ cerr<<line<<"\n"; } cerr<<flush; getch(); exit(0); }catch(exception){ ifstream RE("RE"); string line; while(getline(RE,line)){ cerr<<line<<"\n"; } cerr<<flush; getch(); exit(0); }
bool allCorrect=true; vector<bool> outputCorrect(testCases+1);
for(int i=1;i<=testCases;++i){ outputCorrect[i]=Judge(i); if(!outputCorrect[i]){ allCorrect=false; } }
cerr<<"\n"; if(allCorrect){ ifstream AC("AC"); string line; while(getline(AC,line)){ cerr<<line<<"\n"; } cerr<<flush; }else{ ifstream WA("WA"); string line; while(getline(WA,line)){ cerr<<line<<"\n"; } cerr<<flush; }
string ret[2]{"WA","AC"}; cerr<<"For each testcase : "<<"\n\n"; for(int i=1;i<=testCases;++i){ cerr<<right<<setw(3)<<i<<". "<<flush; cerr<<ret[outputCorrect[i]]<<" "<<flush; cerr<<"Execution time : "<<right<<setw(4)<<costTime[i-1]<<" ms"<<endl; } cerr<<flush;
getch(); }
#endif
|
競賽中不會出現的 C++ 功能
多執行續 thread 函式庫
1 2 3 4 5 6 7 8
| thread run{RunCode,timeLimit};
this_thread::sleep_for(chrono::milliseconds(timeLimit+20))
run.detach();
run.join();
|
其它題目
可以去雲端硬碟下載。這裡有一些題目。Mega