[模板]数据生成与对拍
[模板]数据生成与对拍
不断完善中...
对拍
轻便装(比赛用)
#include <bits/stdc++.h>
using namespace std;
const string file1 = ".exe";
const string file2 = ".exe";
const string random = ".exe";
const bool TLEstop = false;
void getseed() {
static ofstream fout("seed");
fout << rand();
}
void run(string f , string input , string output) {
int t = clock();
printf("running %s\n" , f.c_str());
if(system((f + " < " + input + " > " + output).c_str()) != 0) {
printf("\tRuntimeError\n");
exit(0);
}
printf("\tfinished in %d ms.\n" , clock() - t);
if(clock() - t > 1000 && TLEstop)
system("pause");
}
int main() {
srand(time(0));
int cnt = 0;
while(true) {
printf("#%d\n" , ++cnt);
getseed();
run(random , "seed" , "input.txt");
run(file1 , "input.txt" , "output1.txt");
run(file2 , "input.txt" , "output2.txt");
if(system("fc output1.txt output2.txt")) {
puts("WrongAns");
return 0;
}
}
return 0;
}
完整版(平时用)
#include <bits/stdc++.h>
using namespace std;
string randomfile = "random.exe";
string file1 = "#1.exe";
string file2 = "#1-1.exe";
bool TLEstop = true;
int limit = 1000;
//说明一下,随机数据生成使用的srand((unsigned)time(0))中time(0)的单位为秒,这也就意味着两次时间差很小的数据得到的随机种子是一样的,即生成的数据一模一样,这就需要从外面读入种子而保证生成的数据不同
void putseed() {
ofstream fout("seed");//以输出方式打开文件
fout << (unsigned)rand() * rand() * rand();
fout.close();
}
int main() {
srand((unsigned)time(0));
int sum1 = 0;
int sum2 = 0;
int cnt = 0;
while(true) {
++cnt;
putchar('\n');
printf("<========================#%d========================>\n" , cnt);
//random
puts(randomfile.c_str());
puts("\trunning");
putseed();
system((randomfile + " < seed" + " > input.txt").c_str());
puts("\tfinished");
putchar('\n');
//file1
int t = clock();
puts(file1.c_str());
puts("\trunning");
if(system((file1 + " < input.txt > output1.txt").c_str()) != 0) {
puts("\tRE");
break;
}
puts("\tfinished");
printf("\t%dms\n" , clock() - t);
printf("\t平均用时:%.3fms\n" , 1.0 * (sum1 += clock() - t) / cnt);
if(TLEstop && clock() - t > limit) {
puts("TLE");
system("pause");
}
putchar('\n');
//file2
t = clock();
puts(file2.c_str());
puts("\trunning");
if(system((file2 + " < input.txt > output2.txt").c_str()) != 0) {
puts("\tRE");
break;
}
puts("\tfinished");
printf("\t%dms\n" , clock() - t);
printf("\t平均用时:%.3fms\n" , 1.0 * (sum2 += clock() - t) / cnt);
if(TLEstop && clock() - t > limit) {
puts("TLE");
system("pause");
}
putchar('\n');
if(system("fc output1.txt output2.txt")) {
puts("WA");
break;
}
}
system("start input.txt");
return 0;
}
测评自动机
请确认数据文件夹中没有任何其它文件,且读入文件以".in"为后缀
采用多线程监视程序超时情况
数据文件默认为下面形式(*代表任意字符):
*1.in *1.*
*2.in *2.*
......
第二版
加入了超时强行退出机制
#include <direct.h>
#include <io.h>
#include <fstream>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <windows.h>
#include <algorithm>
#include <ctime>
#include <pthread.h>
using namespace std;
string path = "call//";//数据路径
string tested = "#3.exe";//被测评程序
int limit = 3000;//ms 时限
string a;
int reval;
bool TLE_check;
bool fini;
bool fini2;
int run_time;
//=======================================================
void* run_(void* args)
{
run_time = clock();
reval = system(a.c_str());
run_time = clock() - run_time;
fini = true;
}
void* limit_(void* args)
{
int t = 0;
while(t < limit) {
Sleep(50);
t += 50;
if(fini)break;
}
if(!fini) {
system(("TASKKILL /F /IM " + tested + " /T").c_str());
TLE_check = true;
}
fini2 = true;
}
//========================================================
vector <string> file;
void GetAllFiles() {//获取文件名,不用管
long hFile = 0;
struct _finddata_t fileinfo;
string p;
if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) != -1)
{
// label: ;
system("cls");
do {
if(p.assign(fileinfo.name) != "." && p.assign(fileinfo.name) != "..")
file.push_back(p.assign(fileinfo.name) );
} while(_findnext(hFile, &fileinfo) == 0);
_findclose(hFile);
}
}
struct node{
string s;
int key;//文件序号
void getkey() {
key = 0;
for(int i = 0 ; i < s.size() ; i++)
if(s[i] >= '0' && s[i] <= '9') {
if(i != 0) if(s[i - 1] < '0' || s[i - 1] > '9')key = 0;
key = key * 10 + s[i] - '0';
}
}
};
vector <node> input;
vector <node> ans;
bool cmp(node a , node b) {
return a.key < b.key;
}
int main() {
GetAllFiles();
int siz = file.size();
for(int i = 0 ; i < siz ; i++) {
node tmp;
tmp.s = file[i];
tmp.getkey();
if(file[i].substr(file[i].size() - 2) == "in") {
input.push_back(tmp);
}
else
ans.push_back(tmp);
}
sort(input.begin() , input.end() , cmp);
sort(ans.begin() , ans.end() , cmp);
for(int i = 0 ; i < input.size() ; i++) {
printf("#%d\n" , i + 1);
cout << input[i].s << endl;
cout << ans[i].s << endl;
putchar('\n');
}
puts("check the files");
system("pause");
int TLE = 0 , WA = 0 , AC = 0 , RE = 0;
int tot = 0;
int tim[110];
int sta[110];
for(int k = 0 ; k < input.size() ; k++) {
string i = input[k].s;
string o = ans[k].s;
tot++;
tim[tot] = 0;
int t = clock();
//=============
a = (tested + " < " + path + i + " > output.txt");
pthread_t close;
pthread_t run;
int ret = 0;
reval = -1;
TLE_check = false;
fini = fini2 = false;
ret = pthread_create(&run, NULL, run_, NULL);
ret = pthread_create(&close, NULL, limit_, NULL);
while(!fini && !fini2) {
Sleep(50);
}
//=============
if(reval != 0 && TLE_check == false) {
RE++;
sta[tot] = 0;
continue;
}
tim[tot] = run_time;
if(TLE_check == true) {
TLE++;
sta[tot] = 1;
continue;
}
if(system(("fc output.txt " + path + o).c_str())) {
WA++;
sta[tot] = 2;
continue;
}
AC++;
sta[tot] = 3;
}
for(int i = 1 ; i <= tot ; i++) {
printf("#%d:\n" , i);
puts(("\t" + (string)(sta[i] <= 1 ? (sta[i] == 0 ? "RE" : "TLE") : (sta[i] == 2 ? "WA" : "AC") ) ).c_str());
if(sta[i] != 0) {
printf("\ttime:%dms\n" , tim[i]);
}
}
putchar('\n');
printf("得分:%.3f" , 100.0 * AC / tot );
//等各个线程退出后,进程才结束,否则进程强制结束了,线程可能还没反应过来;
pthread_exit(NULL);
return 0;
}
第一版
#include <direct.h>
#include <io.h>
#include <fstream>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <windows.h>
#include <algorithm>
#include <ctime>
using namespace std;
string path = "data//";//数据路径
string tested = "1.exe";//被测评程序
int limit = 3000;//ms 时限
vector <string> file;
void GetAllFiles() {//获取文件名,不用管
long hFile = 0;
struct _finddata_t fileinfo;
string p;
if((hFile = _findfirst(p.assign(path).append("\\*").c_str(),&fileinfo)) != -1)
{
label: ;
system("cls");
do {
if(p.assign(fileinfo.name) != "." && p.assign(fileinfo.name) != "..")
file.push_back(p.assign(fileinfo.name) );
} while(_findnext(hFile, &fileinfo) == 0);
_findclose(hFile);
}
}
struct node{
string s;
int key;//文件序号
void getkey() {
key = 0;
for(int i = 0 ; i < s.size() ; i++)
if(s[i] >= '0' && s[i] <= '9') {
if(i != 0) if(s[i - 1] < '0' || s[i - 1] > '9')key = 0;
key = key * 10 + s[i] - '0';
}
}
};
vector <node> input;
vector <node> ans;
bool cmp(node a , node b) {
return a.key < b.key;
}
int main() {
GetAllFiles();
int siz = file.size();
for(int i = 0 ; i < siz ; i++) {
node tmp;
tmp.s = file[i];
tmp.getkey();
if(file[i].substr(file[i].size() - 2) == "in") {
input.push_back(tmp);
}
else
ans.push_back(tmp);
}
sort(input.begin() , input.end() , cmp);
sort(ans.begin() , ans.end() , cmp);
for(int i = 0 ; i < input.size() ; i++) {
printf("#%d\n" , i + 1);
cout << input[i].s << endl;
cout << ans[i].s << endl;
putchar('\n');
}
puts("check the files");
system("pause");
int TLE = 0 , WA = 0 , AC = 0 , RE = 0;
int tot = 0;
int tim[110];
int sta[110];
for(int k = 0 ; k < input.size() ; k++) {
string i = input[k].s;
string o = ans[k].s;
tot++;
tim[tot] = 0;
int t = clock();
if(system((tested + " < " + path + i + " > output.txt").c_str()) != 0) {
RE++;
sta[tot] = 0;
continue;
}
tim[tot] = clock() - t;
if(tim[tot] > limit) {
TLE++;
sta[tot] = 1;
continue;
}
if(system(("fc output.txt " + path + o).c_str())) {
WA++;
sta[tot] = 2;
continue;
}
AC++;
sta[tot] = 3;
}
for(int i = 1 ; i <= tot ; i++) {
printf("#%d:\n" , i);
puts(("\t" + (string)(sta[i] <= 1 ? (sta[i] == 0 ? "RE" : "TLE") : (sta[i] == 2 ? "WA" : "AC") ) ).c_str());
if(sta[i] != 0) {
printf("\ttime:%dms\n" , tim[i]);
}
}
putchar('\n');
printf("得分:%.3f" , 100.0 * AC / tot );
return 0;
}
数据生成
基础模板
#include <bits/stdc++.h>
using namespace std;
int random(int r , int l = 1) {
int x = 0;
for(int i = 1 ; i <= 29 ; i++)
x = (x << 1) + (rand() & 1);
return x % (r - l + 1) + l;
}
int main() {
unsigned seed;
cin >> seed;
srand(seed * time(0));
return 0;
}
随机生成树
//针对洛谷P3397:LCA模板
#include <bits/stdc++.h>
using namespace std;
int random(int r , int l = 1) {
return (long long) rand() * rand() % (r - l + 1) + l;
}
pair <int,int> ed[1000010];
int dict[1000010];//用于打乱结点编号,有些有向图不适用
int main() {
unsigned seed;
cin >> seed;
seed *= time(0);
srand(seed);//外界输入种子
int n = random(500000) , m = random(500000);
for(int i = 1 ; i <= n ; i++)
dict[i] = i;
random_shuffle(dict + 1 , dict + n + 1);
for(int i = 1 ; i < n ; i++) {
ed[i].first = random(i);
ed[i].second = i + 1;
}
printf("%d %d %d\n" , n , m , random(n));
random_shuffle(ed + 1 , ed + n);//随机打乱
for(int i = 1 ;i < n ; i++)
printf("%d %d\n" , dict[ed[i].first] , dict[ed[i].second]);
for(int i = 1 ; i<= m ; i++)//查询LCA
printf("%d %d\n" , random(n) , random(n));
return 0;
}
随机生成图
//无向图,带权边 有向图适当修改即可
#include <bits/stdc++.h>
#define ull unsigned long long
using namespace std;
int random(int r , int l = 1) {
return (long long) rand() * rand() * rand() % (r - l + 1) + l;
}
#define nn 100010
map <ull , bool> h;
int n , m ;
int dict[nn];
struct node {
int x , y;
} ed[nn * 5];
#define value(_ , __) ((ull)n * (_) + (__))//hash
int main() {
unsigned seed;
cin >> seed;
seed *= time(0);
srand(seed);
int n = random(300 , 2) , m = random(n * 10 , n) ;
if(m > n * (n - 1) / 2)
m = n * (n - 1) / 2;
for(int i = 1 ; i <= n ; i++)
dict[i] = i;
for(int i = 2 ; i <= n ; i++) {//生成树以保证图连通
ed[i - 1].y = i;
ed[i - 1].x = random(i - 1);
h[value(ed[i - 1].x , ed[i -1 ].y)] = true;
h[value(ed[i - 1].y , ed[i -1 ].x)] = true;
}
for(int i = n ; i <= m ; i++) {
int x , y;
do
x = random(n) , y = random(n);
while(x == y || h[value(x , y)] == true);//如果m开得太接近n*(n-1)/2,这里会很吃力
ed[i].x = x , ed[i].y = y;
h[value(x , y)] = h[value(y , x)] = true;
}
random_shuffle(ed + 1 , ed + m + 1);
random_shuffle(dict + 1 , dict + n + 1);
printf("%d %d\n" , n , m);
for(int i = 1 ; i <= m ; i++) {
printf("%d %d %d\n" , dict[ed[i].x] , dict[ed[i].y] , random(1e6));
}
return 0;
}
造数据
以洛谷为标准
上传压缩包的要求
- 直接将若干数据点打包成一个 zip 压缩包,rar 和其他格式不能成功。
- 输入数据和输出数据应当成对出现,其输入数据文件的扩展名为
.in
而输出文件的扩展名为.out
。- 没有任何文件夹或者其他无关文件,压缩后大小不超过 50M。
- 测试点文件名中只能允许有连续的一段数字,例如
game001.in
可以,而T1-1.in
或game.in
不可以。测试点配置要求
- 普通用户的测试点数量不能超过 50 对,单测试点最多运行 10s,内存 512M。
- 如果需要设置子任务,需要从 0 开始编号。
题目测试点配置文件
在上传题目数据时可以直接在网页中设置测试点的时间、内存限制等信息,但如果重复更新数据,每次都要重设很麻烦,就可以使用测试点配置文件。
详见:题目测试点配置文件
Special Judge 使用说明
当一个题目可以接受多种正确答案,即有多组解的时候,题目就必须被 Special Judge。 Special Judge 程序使用输入数据和一些其他信息来判答你程序的输出,并将判答结果返回。
自定义计分脚本
有的时候出了一道题想要自定义比较复杂的计分策略,但是单靠 Subtask 的组合无法满足,这时候可以使用计分脚本。
详见:自定义计分脚本
交互题功能说明
交互题既用户提交的程序,通过出题人提供的交互库,与判题程序(SPJ)进行交互并获得输入、解答问题。
详见:交互题功能说明
#include <bits/stdc++.h>
using namespace std;
string random = "random.exe"; //随机数据文件
string stdcode = "std.exe"; //标准程序
string name = "replace"; //数据文件名(不能含空格)
string itos(unsigned x) {
string s;
do
s = (char)(x % 10 + '0') + s , x /= 10;
while(x != 0);
return s;
}
void putseed() {
ofstream fout("seed");
fout << (unsigned)rand() * rand() * rand();
fout.close();
}
int main() {
system("md data");
for(int i = 1 ; i <= 50 ; i++) {//数据组数
string in = name + "_" + itos(i) + ".in";
string out =name + "_" + itos(i) + ".out";
putseed();
puts(("data " + itos(i) + " making").c_str());
system( (random + " < seed > " + in).c_str() );
puts(("data " + itos(i) + " .in finished").c_str());
system( (stdcode + " < " + in + " > " + out).c_str() );
puts(("data " + itos(i) + " .out finished").c_str());
system( ("move " + in + " data\\" + in).c_str());
system(("move " + out + " data\\" + out).c_str());
}
return 0;
}