詳解—對拍


對拍

注;  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)

 1 int Sum[100005];
 2 int main()
 3 {
 4     freopen("data.in","r",stdin);                  //從文件data.in中讀入數據
 5     freopen("ZhengJie.out","w",stdout);    //輸出的結果存在ZhengJie.out文件中
 6     int i,n,m,tmp,x,y;
 7     scanf("%d%d",&n,&m);
 8     for(i=1;i<=n;i++)
 9     {
10           scanf("%d",&tmp);
11           Sum[i]=Sum[i-1]+tmp;
12     }
13     for(i=1;i<=m;i++)
14     {
15          scanf("%d%d",&x,&y);
16          printf("%d\n",Sum[y]-Sum[x-1]);
17     }
18 }
19 
20 /*
21    我們把這個程序保存為ZhengJie.cpp,但這個程序是否正確呢?
22    我們再寫一個暴力程序來驗證它
23 */

第二步:寫一個暴力程序,這里我寫的是暴力枚舉(BaoLi.cpp)

 

 1 int a[100005];
 2 int main()
 3 {
 4     freopen("data.in","r",stdin);            //注意,暴力程序讀入的數據仍然是data.in
 5     freopen("BaoLi.out","w",stdout);    //暴力程序輸出的結果是BaoLi.out
 6     int n,m,i,j,x,y,ans;
 7                scanf("%d%d",&n,&m);
 8                for(i=1;i<=n;i++)scanf("%d",&a[i]);
 9                for(i=1;i<=m;i++)
10                {
11                       scanf("%d%d",&x,&y);
12                       ans=0;
13                       for(j=x;j<=y;j++)ans+=a[j];
14                       printf("%d\n",ans);
15                }
16 }
17    我們把這個程序保存為BaoLi.cpp   注意:我們不在乎暴力程序效率,只需要保證它的結果是正確的就行了。

 

第3步:我們還需要一個生成隨機數據的程序(MakeData.cpp)

 

 1 //該程序按照題目給定的格式生成隨機數據。
 2 #include<cstdlib>                                         //加入這個包才能使用隨機函數rand()
 3 #include<cstdio>
 4 #include<ctime>                                           //加入這個包就能以時間為種子初始化隨機函數
 5 #include<iostream>
 6 using namespace std;
 7 int main()
 8 {
 9     freopen("data.in","w",stdout);                        //注意:該程序生成的數據到data.in中
10     srand(time(NULL));                                          //重要:初始化隨機函數,以時間為種子
11     int n=rand()%10000+1;                                 //生成一個1到10000之間的隨機整數n
12     int m=rand()%10000+1;
13     printf("%d %d\n",n,m);
14     for(int i=1;i<=n;i++)printf("%d ",rand()%20000-rand()%10000);//生成-10000到10000間的數字
15     printf("\n");
16     for(int i=1;i<=m;i++)
17     {
18            int x=rand()%n+1;                                     //保證生成的數據是x<=y
19            int y=x+rand()%n+1;
20            if(y>n)y=n;
21            printf("%d %d\n",x,y);
22     }
23 }
24 注意:
25 rand()只能生成0到32767之間的隨機整數,如果要生成1到50000之間的整數,可以寫成:
26 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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM