首页 > 其他 > 详细

对拍简介

时间:2020-04-03 22:11:03      阅读:63      评论:0      收藏:0      [点我收藏+]

简介

对拍是一种常用的竞赛技巧,主要是在 NOI 赛事中适用的。

目的是在无法得知评测结果的情况下,防止挂分。(例如你样例都过了,但是其实代码有大坑)

其原理是制造随机数据并写一个暴力,然后进行结果比对,倘若有差异则你成功的造出来一组 Hack 数据。

当然前提是你的暴力确定没有问题。

随机数据

对拍的核心内容,主要用到 rand()srand() 两个函数。

代码如下。

#include <bits/stdc++.h>
using namespace std;
 
int main()
{
	srand(time(0));//让若去掉这一行的话,就无法达到随机数据。
	int n,m,S;
	n=rand()%100+1;
	m=rand()%200+1;
	S=1;
	printf("%d %d\n",n,m);//制造有向图。
	for (int i=1;i<=m;i++){
		int u,v,w;
		u=rand()%n+1;
		v=rand()%n+1;//范围为 0~n
		w=rand()%1000000;//范围为 0~1000000-1
		printf("%d %d %d\n",u,v,w);
	}
	
	return 0;
}

以上是 最短路模板 的随机数据代码。

其实很容易理解的啦。

脚本

这是将所有代码连接起来的重要程序,全部写好之后,在这里查看运行结果。

#include<iostream>  
#include<windows.h>  
using namespace std;  
int main()  
{  
    int t=50;
    while(t)//代表对拍次数。
    {  
      	t--;  
        system("data.exe > data.txt");  
        system("Floyd.exe < data.txt > Floyd.txt");  
        system("Dijkstra.exe < data.txt > Dijkstra.txt");  
        if(system("fc Dijkstra.txt Floyd.txt"))   break;  
    }//以上请背下来。(也没有什么更好的方法啦)
    if(t==0) cout<<"Accept"<<endl;
    else cout<<"Wrong Answer"<<endl;  
 
    return 0;  
}  

就是酱紫。

  1. Dijkstra.exe 当做运行程序。(即你的正解)

  2. Floyd.exe 当做暴力程序。

运行

以下给出我的两份代码。

Dijkstra

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#define N 100010
#define M 1000010
#define maxd 1061109567
using namespace std;

int n,m;
int head[N],dis[N],cnt=0;
bool use[N];
struct node{
	int next,to,val;
}edge[M];
priority_queue<pair<int,int> >q;
//为了避免重载小于号。
//pair的first用于存储dis[]的相反数(变小根堆),second用存储编号。

void addedge(int x,int y,int z){
    cnt++;
    edge[cnt].next=head[x];
    edge[cnt].to=y;
    edge[cnt].val=z;
    head[x]=cnt;
    return;
}

void dij(){
	for(int i=1;i<=n;i++) dis[i]=maxd;
	memset(use,false,sizeof(use));
	q.push(make_pair(0,1));
	dis[1]=0;

	while(!q.empty()){
		int now=q.top().second;
		q.pop();
		if(use[now]) continue;
		use[now]=true;
		for(int i=head[now];i;i=edge[i].next){
			int y=edge[i].to;
			int z=edge[i].val;
			if(dis[y]>dis[now]+z){
				dis[y]=dis[now]+z;
				q.push(make_pair(-dis[y],y));
			}
		}
	}
	return;
}

int main(){
	scanf("%d %d",&n,&m);
	int u,v,w;
	for(int i=1;i<=m;i++){
		scanf("%d %d %d",&u,&v,&w);
		addedge(u,v,w);
	}
	dij();
	for(int i=1;i<=n;i++) printf("%d ",dis[i]);
	//system("pause");
	return 0;
}

Floyd

#include<cstdio>
#include<queue>
#include<iostream>
#include<cstring>
using namespace std;

const int N=100010,M=1000010;

int n,m,tot;
int edge[N][N];

int main(){
	scanf("%d %d",&n,&m);
	int u,v,w;
	
	for(int i=1;i<=m;i++){
		scanf("%d %d %d",&u,&v,&w);
		edge[u][v]=w;
	}
	
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				if(edge[i][j]>edge[i][k]+edge[k][j])
					edge[i][j]=edge[i][k]+edge[k][j];
	
	for(int i=1;i<=n;i++){
		printf("%d ",edge[1][i]);
	}
	return 0;
}

可见这个暴力确实很暴力

然后就是愉快的对拍时间,结果大概是酱紫:

技术分享图片

当然如果想要知道错误回事什么样子...自己故意放一个错误的代码吧。

另外方法

是这个样子的。

脚本:

#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;

int main(){
	for(int T=1;T<=100000;T++){
		system("E:\\random.exe");
		double st=clock();
		system("E:\\sol.exe");
		double ed=clock();
		system("E:\\bf.exe");
		if(system("fc E:\\data.out E:\\data.ans")){
			printf("Wrong Answer");
		}
		else printf("Accepet,测试点 #%d,用时 %.0lfms\n",T,ed-st);
	}
	return 0;
}

数据生成器:

#include<cstdlib>
#include<ctime>
#include<cstdio>
using namespace std;

int a[100010],b[100010];

int random(int n){
	return (long long)rand()*rand()%n;
}

int main(){
	freopen("data.in","w",stdout);
	srand((unsigned)time(0));
	int m=20;
	printf("%d %d\n",random(m),random(m));
	fclose(stdout);
	return 0;
}

来个暴力:(这也叫暴力?)

#include<cstdio>
using namespace std;

int main(){
	freopen("data.in","r",stdin);
	freopen("data.ans","w",stdout);
	int a,b;
	scanf("%d %d",&a,&b);
	printf("%d\n",a+b);
	fclose(stdin);fclose(stdout);
	return 0;
}

放个错误代码:

#include<cstdio>
using namespace std;

int main(){
	freopen("data.in","r",stdin);
	freopen("data.out","w",stdout);
	int a,b;
	scanf("%d %d",&a,&b);
	printf("%d\n",a+b);
	if(a+b==20) printf("hahaha\n");//多了一行...
	fclose(stdin);fclose(stdout);
	return 0;
}

运行结果与上图差不多,就不上图片了。

总结

  1. 以上两种代码,各有优缺点,请凭借个人喜好使用。
  2. 这是 Windows 下的对拍(但是考试是 NOI Linux 呀),所以...有待更新。

未完待续。

对拍简介

原文:https://www.cnblogs.com/lpf-666/p/12629151.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!