对拍详解

                                                 对拍详解                                                                                                                                                                ——HM      

    对拍是家中写题、考场中写题判断自己的程序答案是否正确的一种技巧,当打完时可以写一个对拍程序来判断一下自己的代码。大体思路就是:写一个暴力,写一个数据生成器,将生成的数据分别输入在你的正解与暴力中,因为暴力的程序一定对,所以只要将暴力得来的答案与你写的代码得到的答案相比较,若有不对立刻跳出,从而做到保证程序答案的正确性。

    对拍以下几点不适用:

1、对拍只能保证正确性,不能保证最优性,即只能保证答案正确,不能保证TLE或MLE等。

2、对拍无法使正解就是暴力的题目答案正确。

下面来讲如何实现对拍:

首先写一个正解、一个保证答案正确的暴力(在家做题可以贴一个题解,答案正确就行),再写一个数据随机生成器(下面会有样例),然后背一个对拍程序(cpp文件),编译一遍正解、暴力、数据生成器生成3个exe,将上述所有放入一个文件夹中(建议不要放在桌面),运行对拍程序直接根据运行结果判断即可。

有点难懂,举个例子:

    假如我编了一个Dijkstra优先级队列优化最短路(顺便宣传一下自己的博客),不能确定正确性,于是编了一个Floyd,并写了一个对拍程序、一个数据生成器,将Dijkstra、Floyd分别命名为Dijkstra.cpp、Floyd.cpp,按照输入格式编了一个数据生成器:

#include 
using namespace std;

int main()
{
	srand(time(0));
	int n,m,S;
	n=rand()%1000+1;
	m=rand()%2000+1;
	S=1;
	printf("%d %d %d\n",n,m,S);
	for (int i=1;i<=m;i++){
		int u,v,w;
		u=rand()%n+1;
		v=rand()%n+1;
		w=rand()%1000000000;
		printf("%d %d %d\n",u,v,w);
	}
	
	return 0;
}

解释一下rand()函数用来生成随机数,但若不加srand(time(0))这个语句,则所有生成的数据都是一样的,就没有意义了;随机数模一个数在加一个数可以确定其范围,,比如随机数x,x=x%a+b可以使x在a到b的范围内。其实这就是将原来的输入全部改为输出即可。

然后编一个对拍程序:

#include  
#include  
using namespace std;  
int main()  
{  
    int t=10;
    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<<"no error"<

变量t指的是你要测试数据的组数,将数据生成器命名为data.cpp,按上面的程序打一遍就行了,大概意思就是运行一遍另外三个程序exe,将数据生成器生成的数据放在data.txt中,标程与暴力分别读入数据,并进行比较,若不同,则直接跳出,此时t未减到0,故最后判断出错误,因为“fc”函数,会将两个程序的输出打印出来。

全部编译一遍,效果如下图所示

对拍详解_第1张图片

运行check.cpp(就是对拍程序),就行啦,效果如下图:

对拍详解_第2张图片

就说明正解正确啦!

现在如果有错误的话就如下图:

对拍详解_第3张图片

其他程序的话同理就行了。

最后一条建议:编数据时最好不要用原题数据,暴力会卡死,毕竟只是保证正确性,数据小一点就好。

你可能感兴趣的:(技巧专栏)