标签:出现 代码 png 运行时 ted 数据结构 block 答案 dom
在漫长的\(OI\)生涯中,你肯定遇到过这些情况
这时候,我们就可以试试随机数据生成与对拍`
顾名思义,就是针对我们的需求生成随机的数据。比如生成随机的整数序列,生成随机的树,生成随机的图。
对拍说白了就是对答案,举个栗子:在文化课中,对于同一道填空题,我们在写出自己的答案后,可能会找其他同学对一下答案,看是不是一样的。放在\(OI\)中,就是对于同一道题目,两个不同的人写了两份不同的程序,再针对同一组数据,看看两份程序的输出结果是否一样。
比方说在无法获得实时评测反馈的比赛中(\(NOIp\)),对于一道题目,你思考并实现了一个“高分解法”,但不能确保这个程序是否完全正确,这种情况下,就可以考虑编写一份随机数据生成程序,一份用正确但是会\(TLE\)的暴力算法写的程序,然后将两个程序对拍,看是否输出结果一致。
要是暴力都不会打,那就输出随机数据骗分吧
参考《算法竞赛进阶指南》P439
先给出随机数据生成的模板,适用于此文中所有的生成数据方法
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int random(int n)//生成一个[0,n-1]范围内的数
{
return (long long)rand()*rand()%n;
}
int main()
{
freopen("data.in","w",stdout);
//将生成的数据输出到名为data.in的文件中
srand((unsigned)time(0));
//具体内容...
return 0;
}
生成数据的方法:
随机生成整数序列
//随机生成n(n<=1e5)个绝对值在1e8之间的整数
int n=random(100000)+1,x;
for(int i=1;i<=n;i++)
printf("%d ",random(x*2+1)-x);
putcha('\n');//可有可无
随机生成排列
//随机生成1~n(n<=1e5)的排列
//STL的方法
int n=random(100000)+1,a[100050];
for(int i=1;i<=n;i++)
a[i]=i;
random_shuffle(a+1,a+n+1);//库文件algorithm
for(int i=1;i<=n;i++)
printf("%d ",a[i]);
//瞎搞方法
int n=random(100000)+1,bool vis[100050];
for(int i=1;i<=n;i++)
{
int x=random(n)+1;
while(vis[x]==1)
x=random(n)+1;
vis[x]=1;printf("%d ",x);
}
//随机生成m个[1,n]的子区间
for(int i=1;i<=m;i++)
{
int l=random(n)+1;
int r=random(n)+1;
if(l>r) swap(l,r);
printf("%d %d\n",l,r);
}
//随机生成一棵n个点带边权(<=100000)的树
for(int i=2;i<=n;i++)
{
int fa=random(i-1)+1;
int val=random(100000)+1;
printf("%d %d %d\n",fa,i,val);
}
//随机生成一张n个点,m条边的无向图.
pair<int,int> e[];//[]内填写数组大小
map<pair<int,int>,bool> h;//库文件map
//先生成一棵树,保证联通
int n=random(具体大小),m=random(具体大小);
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;
}
//在生成剩余的m-n+1条边
for(int i=n;i<=n;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+m+1);//库文件algorithm
for(int i=1;i<=m;i++)
printf("%d %d\n",e[i].first,e[i].second);
//生成一条有n个节点的链
int n=random(1000)+1;printf("%d\n",&n);
int root=random(n)+1;bool vis[100000];
vis[root]=1;int last=root;
for(int i=1;i<n;i++)
{
int x=random(n)+1;
while(vis[x]==1) x=random(n)+1;
printf("%d %d\n",last,x);
last=x;vis[x]=1;
}
//生成一条有n个节点的菊花图
int n=random(1000)+1;printf("%d\n",n);
int root=random(n)+1;
for(int i=1;i<=n;i++)
{
if(i==root) continue;
printf("%d %d\n",root,i);
}
那么如何实现对拍呢?
假设此时我们已经编写好了三个程序:
依次编译这三个程序,得到三个exe文件,然后运行如下程序即可。
#include <cstdlib>
#include <iostream>
#include <cstdio>
#include <ctime>
using namespace std;
int main()
{
for(int T=1;T<=100;T++)//T即为测试数据的组数
{
system("C:\\random.exe");//运行数据生成的程序
// 获取正解程序的运行时间,Windows下单位为ms
double st=clock();
system("C:\\sol.exe");//运行正解程序
double ed=clock();
system("C:\\bf.exe");//运行暴力程序
if(system("fc data.out data.ans"))
//对比正解与暴力程序的输出结果,如果不同
{
puts("Wrong Answer");
return 0;
}
else printf("Accepted, 测试点 #%d, 用时 %.0lfms\n",T,ed-st);
//如果输出结果一样,那么输出程序运行时间
}
return 0;
}
bf
是std,sol
是我的95分程序,rand
是针对这道题目写出来的随机数据生成器,对拍
即上文提到的那个模板。sol
程序的输出结果和bf
的输出结果一样,那么它就会输出Accepted
和我们这个col
程序对于这一组数据的运行时间data.in
这个文件开始思考自己程序的bug就行了完结撒花
typed by zbwer 2019-08-31
部分代码引用李煜东的《算法竞赛进阶指南》
标签:出现 代码 png 运行时 ted 数据结构 block 答案 dom
原文地址:https://www.cnblogs.com/fengzi8615/p/11699820.html