比赛中常用对拍来判断自己yy的算法有没有错误,做题时也可以用对拍Debug,这里介绍一下(本人)常用对拍程序的写法,以及许多常用模型的数据生成器
实现
在程序目录新建一个文件,把后缀改成bat,然后在里面输入这些
@echo off
:duan2baka
dataspawner > data.txt
my < data.txt > my.txt
std < data.txt > std.txt
fc my.txt std.txt
if errorlevel 1 pause
goto duan2baka
看不懂?这里一句一句解释
line1
@echo off
的意思是关闭回显,大概就是你不打这个系统的指令就会显示出来,极其不美观
大概会出这些东西
line2
这个东西是和c++的goto差不多的,在后面line8的时候跳回到这一行,来实现循环的效果
line3
首先你要生成一组随机数据,用你写的dataspawner.exe来生成一个data.txt,这个符号的方向个人认为就像dataspawner把data.txt拉出来一样,贼形象
line4
把拉出来的data.txt塞到my.exe(这是自己的程序)里当输入,再拉出来个my.txt,为自己程序的输入
line5
同上,std是正确的程序(考试的时候大多数为暴力)
line6~8
fc是比较函数,比较你的答案和std的答案有没有差别,如果有,就暂停,否则跳回到标记的位置
如果数据有差异,对拍程序就会立即暂停,此时关闭对拍程序,目录下的data.txt就是造成答案不同的数据,my.txt是你的输出,std.txt是标程的输出,可以针对这组数据来查找自己哪里错误了
数据生成器
要保证每次的数据都不相同,常见的办法是将系统时间作为种子srand(time(NULL)),但是系统时间一秒才更换一次,这样造成的效率就会变得很低
对于这个问题,可以将line3改成这个dataspawner %random% > data.txt
意思是让系统随机生成一个参数传入datamaker中,这样每次对拍都会有不同的种子啦!
常用模型
生成一张N点M边联通图
#include<bits/stdc++.h>
#define random(a,b) ((a)+rand()%((b)-(a)+1))
using namespace std;
const int N=10;
const int M=15;
stringstream str;
int x,y,n,m,seed;
int f[N];
int find(int x){return f[x]==x?f[x]:f[x]=find(f[x]);}
int main(int argc,char *argv[]){
seed=time(NULL);
if(argc){
str.clear();
str<<argv[1];
str>>seed;
}
srand(seed);
n=random(1,N);m=random(-1,M);
for(int i=1;i<=n;i++) f[i]=i;
printf("%d %d\n",n,m);
m=m-n+1;
for(int cnt=1;cnt<n;){
x=rand()%n+1;y=rand()%n+1;
int fx=find(x),fy=find(y);
if(fx==fy){continue;}
f[fy]=fx;
printf("%d %d",x,y);
///printf(" %d",rand());(如果边有权值,用上这段代码;如果没有,忽略这句话)
puts("");
cnt++;
}
for(int i=1;i<=m;i++){
x=rand()%n+1;y=rand()%n+1;
printf("%d %d",x,y);
///printf(" %d",rand());
puts("");
}
return 0;
}
N个数,M个操作,有k种操作
#include<bits/stdc++.h>
#define random(a,b) ((a)+rand()%((b)-(a)+1))
using namespace std;
const int N=200000;
const int M=200000;
const int k=5;
stringstream str;
int x,y,n,m,seed,l,r,k;
int f[N];
int find(int x){return f[x]==x?f[x]:f[x]=find(f[x]);}
int main(int argc,char *argv[]){
seed=time(NULL);
if(argc){
str.clear();
str<<argv[1];
str>>seed;
}
srand(seed);
n=random(1,N);m=random(1,M);
printf("%d %d\n",n,m);
for(int i=1;i<=n;i++) printf("%d ",rand()*rand());
puts("");
for(int i=1;i<=m;i++){
k=random(1,k);
l=random(1,n-1);r=random(l,n);
printf("%d %d %d\n",k,l,r);
}
return 0;
}
生成一棵树
#include<bits/stdc++.h>
#define random(a,b) ((a)+rand()%((b)-(a)+1))
using namespace std;
const int N=10;
const int M=15;
stringstream str;
int x,y,n,m,seed;
int f[N];
int find(int x){return f[x]==x?f[x]:f[x]=find(f[x]);}
int main(int argc,char *argv[]){
seed=time(NULL);
if(argc){
str.clear();
str<<argv[1];
str>>seed;
}
srand(seed);
for(int i=1;i<=n;i++) f[i]=i;
printf("%d\n",n);
for(int cnt=1;cnt<n;){
x=rand()%n+1;y=rand()%n+1;
int fx=find(x),fy=find(y);
if(fx==fy){continue;}
f[fy]=fx;
printf("%d %d",x,y);
///printf(" %d",rand());(如果边有权值,用上这段代码;如果没有,忽略这句话)
puts("");
cnt++;
}
return 0;
}
其他的用到再补吧..