数据生成&对拍 Windows&Linux

前言

  • 对拍是个非常好用的工具,无论在 OI 还是常规情境下,是一个检测代码正确性的工具

数据生成

  • C++ 包含一个随机数据生成函数 rand(),支持生成 [0,MAX_RAND] 的随机数,使用 srand() 设定种子以保证随机性,否则为伪随机,time(0) 返回自 1970.1.1 00:00 起到现在经过的秒数,常作为随机种子,如 srand(time(0))
  • 一般我们像下面那样造数据
int rd(int x) {return (long long)rand()*rand()%x+1;}
  • 或者这样
random_device sd;
mt19937 mk(sd());
int myrand(int l,int r)
{
	uniform_int_distribution<>dis(l,r);
	return dis(mk);
}
  • 这个东东是 2K22 教我的,具体什么原理我也不清楚,一般常用上面的造数据
示例:gen.cpp
#include<bits/stdc++.h>
using namespace std;
int rd(int x) {return (long long)rand()*rand()%x+1;}
int main()
{
    // freopen("data.in","w",stdout);
    /*如果在 Windows 下这个是要非注释*/
    /*因为msjing Windows 写的是 C++ 的 chk,而 Linux 写的是脚本*/
    srand(time(0));
    int m=rd(5);
    cout << m << '\n';
    return 0;
}

对拍准备

  • 对拍操作需要正解代码(暴力也行,就是跑的慢,OI 比赛中常用暴力代码)和待测的代码,没啥注意的,就是常规代码,Windows下要加 freopen

std

示例:std.cpp
#include <bits/stdc++.h>
using namespace std;
int main()
{
	// freopen("data.in","r",stdin);
	// freopen("std.out","w",stdout);
    /*同上*/
    //暴力代码 
    return 0;
}

my

示例:my.cpp
#include <bits/stdc++.h>
using namespace std;
int main()
{
	// freopen("data.in","r",stdin);
	// freopen("my.out","w",stdout);
    /*同上*/
    //代码 
    return 0;
}

对拍程序

  • 当然,对拍最重要的是对拍程序,可以大幅减少我们时间开销(我觉得你应该不想手动运行数据生成,正解,待测代码并一个一个对输出)

  • Windows msjing写的是 C++ 程序,Linux msjing写的脚本

  • 对拍发现文件不一致后,直接退出程序,数据,std 输出,my 输出都会存储到文件里

  • 示例:chk on Windows

  • 如果编译的指令跑不了的话,你就只能手动编译运行了,但是只需要运行一次

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

int main()
{
	int n=500;//500组
	system("g++ gen.cpp -o gen.exe -std=c++14 -O2");
	system("g++ std.cpp -o std.exe -std=c++14 -O2");
	system("g++ my.cpp -o my.exe -std=c++14 -O2");
    /*编译*/
	for (int i=1;i<=n;i++)
	{
		system("gen.exe");
		system("std.exe");
		system("my.exe");
        /*运行*/
		if (system("fc a.out a.ans"))/*文件比较*/
		{
			puts("Wrong Answer");
			return 0;
		}
		printf("AC on test case %d\n",i);
	}
	return 0;
}

  • 示例:chk on Linux

  • 写的脚本,C++ 也行

  • 脚本需要存在 .sh 文件里而不是 .cpp

#!/bin/bash

echo "Compiling programs..."
g++ gen.cpp -o gen -O2 -std=c++14
g++ std.cpp -o std -O2 -std=c++14
g++ my.cpp -o my -O2 -std=c++14

if [ $? -ne 0 ]; then
    echo "Compile Error"
    exit 1
fi

echo "successful"

count=0
while true; do
    count=$((count + 1))
    echo "Testing case $count..."
    ./gen > data.in
    ./std < data.in > std.out
    ./my < data.in > my.out
    if ! diff -q std.out my.out > /dev/null; then
        echo "************************************"
        echo "case $count is Wrong!"
        echo "************************************"
        exit 0
    else
        echo "Case $count Accept!"
    fi
done
  • from
  • 毕竟msjing不会写脚本
  • Linux 由于使用脚本,所以直接写代码,不用 freopen
  • 如果提醒你权限不够,使用 chmod +x chk.sh 增加运行权限
  • 使用 ./chk.sh 直接开始

扩展

获取运行时间

  • 使用 C++ 中clock
double stime = clock();
double etime = clock();
cerr << (etime-stime)/CLOCKS_PER_SEC << endl;
// cerr是错误输出流,可以把时间直接打到控制板上

附:生成图

  • LZY说有锅?
code
#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=10010;
int random(int n)
{
	return (long long)rand()*rand()%n;
}
pair<int,int> e[maxn];
map<pair<int,int>,bool> h;
int main()
{
//	freopen("1.in","w",stdout);
	srand(time(0));
	int n=random(15),m=random(15);
	while (!n) n=random(15),m=random(15);
	printf("%d %d\n",n,m);
	for (int i=1;i<n;i++)
	{
		int fa=random(i)+1;
		e[i]=make_pair(fa,i+1);
		h[e[i]]=h[make_pair(i+1,fa)]=1;
	}
	for (int i=n;i<=m;i++)
	{
		int x,y;
		do
		{
			x=random(n)+1,y=random(n)+1;
		}while (x == y || h[make_pair(x,y)]);
		e[i]=make_pair(x,y);
		h[e[i]]=h[make_pair(y,x)]=1;
	}
	random_shuffle(e+1,e+1+m);
	for (int i=1;i<=m;i++) printf("%d %d\n",e[i].first,e[i].second);
	return 0;
}
posted @ 2026-03-24 11:44  msjing  阅读(23)  评论(0)    收藏  举报