人生如此复杂,机会多得像稠密图,我们没理由认输。尽管我们走不了最短路,但图仍是连通图。TLE之前,没有一个节点叫失败。(You know what's cooking? BOOM~~)!

详解—对拍

对拍

注;  NK版权所有,转载请表明出处

定义:

什么是对拍? 当我们的程序过了样例,是否意味着它一定能AC呢?显然大多数情况下都是不行的。所以我们需要自己设计一些数据来测试我们的程序,但有的题目数据很大,我们肉眼无法看出程序计算的结果是否正确,手工计算又非常耗时,在紧张的比赛中,我们该怎么应对呢?于是有了对拍。 对拍简单的说就是当你写完一个题目的程序以后,再写一个暴力求解该题目的程序,然后自己生成一些测试数据,看同样的数据,两个程序输出的结果是否相同,不同意味着被对拍的程序有问题。以此来帮助你修改程序,提高通过率的方法,我们称为对拍。

对拍的例子1

【题目描述】

输入n个整数,现在有m个形如[x,y]的提问,即问第x个数到第y个数之和是多少?现在需要你写一程序对每个提问做出快速回答。 1<=n<=100000 1<=m<=50000

输入格式: 第一行,两个整数n和m 第二行,n个空格间隔的整数,每个整数的范围在[-10000,10000]之间 接下来m行,每行两个整数x和y,表示一次询问的区间(x<=y)

输出格式: m行,每行一个整数,对应一次提问的答案

输入样例: 5 3 1 3 2 7 9 1 2 2 5 3 4

输出样例: 4 21 9

第一步:此题显然是前缀和,于是写代表正解的程序(ZhengJie.cpp)

 int Sum[100005];
 int main()
{
     freopen("data.in","r",stdin);                  //从文件data.in中读入数据
     freopen("ZhengJie.out","w",stdout);    //输出的结果存在ZhengJie.out文件中
     int i,n,m,tmp,x,y;
     scanf("%d%d",&n,&m);
     for(i=1;i<=n;i++)
     {
           scanf("%d",&tmp);
           Sum[i]=Sum[i-1]+tmp;
     }
     for(i=1;i<=m;i++)
     {
          scanf("%d%d",&x,&y);
          printf("%d\n",Sum[y]-Sum[x-1]);
     }
 }
 
 /*
    我们把这个程序保存为ZhengJie.cpp,但这个程序是否正确呢?
    我们再写一个暴力程序来验证它
 */

第二步:写一个暴力程序,这里我写的是暴力枚举(BaoLi.cpp)

 

 int a[100005];
 int main()
 {
     freopen("data.in","r",stdin);            //注意,暴力程序读入的数据仍然是data.in
     freopen("BaoLi.out","w",stdout);    //暴力程序输出的结果是BaoLi.out
     int n,m,i,j,x,y,ans;
                scanf("%d%d",&n,&m);
                for(i=1;i<=n;i++)scanf("%d",&a[i]);
                for(i=1;i<=m;i++)
                {
                       scanf("%d%d",&x,&y);
                       ans=0;
                       for(j=x;j<=y;j++)ans+=a[j];
                       printf("%d\n",ans);
                }
 }
    我们把这个程序保存为BaoLi.cpp   注意:我们不在乎暴力程序效率,只需要保证它的结果是正确的就行了。

 

第3步:我们还需要一个生成随机数据的程序(MakeData.cpp)

 

 //该程序按照题目给定的格式生成随机数据。
 #include<cstdlib>                                         //加入这个包才能使用随机函数rand()
 #include<cstdio>
 #include<ctime>                                           //加入这个包就能以时间为种子初始化随机函数
 #include<iostream>
 using namespace std;
 int main()
 {
     freopen("data.in","w",stdout);                        //注意:该程序生成的数据到data.in中
     srand(time(NULL));                                          //重要:初始化随机函数,以时间为种子
     int n=rand()%10000+1;                                 //生成一个1到10000之间的随机整数n
     int m=rand()%10000+1;
     printf("%d %d\n",n,m);
     for(int i=1;i<=n;i++)printf("%d ",rand()%20000-rand()%10000);//生成-10000到10000间的数字
     printf("\n");
     for(int i=1;i<=m;i++)
     {
            int x=rand()%n+1;                                     //保证生成的数据是x<=y
            int y=x+rand()%n+1;
            if(y>n)y=n;
            printf("%d %d\n",x,y);
     }
 }
 注意:
 rand()只能生成0到32767之间的随机整数,如果要生成1到50000之间的整数,可以写成:
 rand()%30000+rand()%20000+1

 

第4步:写windows对拍文件(对拍.bat)

注意:今天学的是在Windows下的对拍! 全国比赛是在linux系统里写程序,linux下的对拍我们以后再谈!

 

这里提供两种比较麻烦的数据生成模板 

#include <cstdio>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
    //节点数量 
    int n=100000;
    //文件名 
    char file_name[100]="datax.in";
    
    srand(time(0));
    FILE* f=fopen(file_name,"w");
    fprintf(f,"%d\n",n);
    for(int i=2;i<=n;i++)
    {
        int j=i-1-rand()%7;
        j=j<1?1:j;
        fprintf(f,"%d %d\n",j,i);
    }
    
    return 0;
}

比如说这道题的数据程序(自己感觉比较典型)

 

修改程序如下

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
int main()
{
    srand(time(0));//在第一行保证n是随机的 
    int n=rand()%2000;
    char file_name[100]="1.in";//我是输出在1.in里面的 
    FILE* f=fopen(file_name,"w");
    fprintf(f,"%d ",n);//输出n 
    int k=rand()%2000;
    fprintf(f,"%d\n",n);//输出k 
    for(int i=1;i<=n;i++)
    {
        int u=rand()%2000;
        fprintf(f,"%d ",u);//输出a[i] 
}
    cout<<endl;
    for(int i=2;i<=n;i++)
    {
        int j=i-1-rand()%7;
        j=j<1?1:j;
        fprintf(f,"%d %d\n",j,i);//树的输出 
    }
    
    return 0;
}

看看结果

               

数据是有大有小的

在对拍之前还要注意要先编译所有cpp,保证在同一文件夹下有exe文件

然后就可以愉快的对拍了

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <set>
using namespace std;
int main()
{
    //节点数量 
    int n=100000;
    //边数量
    int m=500000; 
    //文件名 
    char file_name[100]="datax.in";
    
    srand(time(0));
    FILE* f=fopen(file_name,"w");
    fprintf(f,"%d %d\n",n,m);
    static int vertex[100000+5];
    for(int i=2;i<=n;i++)
    {
        int j=(rand()<<15|rand())%i+1;
        vertex[i]=vertex[j];
        vertex[j]=i;
    }
    set<pair<int,int> > edge;
    for(int i=1;i<=m;i++)
    {
        int u,v;
        while(true)
        {
            u=(rand()<<15|rand())%n+1;
            v=u+1+rand()%10;
            if(v<=n&&edge.find(make_pair(u,v))==edge.end())
                break;
        }
        fprintf(f,"%d %d\n",vertex[u],vertex[v]);
        edge.insert(make_pair(u,v));
    }
    return 0;
}

 

posted @ 2019-07-09 17:33  CXYscxy  阅读(16712)  评论(0编辑  收藏  举报
Live2D