1. 程式人生 > >C++對拍

C++對拍

文章目錄

前言

近期考古發現,本人於2017年3月水了一篇對拍。 我發現它實在是水,估計沒多少人看得懂。 作為一個內心善良,樂於助人,無比有愛心的人。

我決定再水一篇對拍。

本文廢話較多,程式碼較噁心,諸君可以跳躍性閱讀。

對拍

解釋

根據百度漢語對“拍”的解釋,好像無法理解這個詞。 簡單來說,就是寫一個數據生成器,然後把生成的資料給兩個不同的程式執行,比較它們輸出的結果。 主要有兩個用途:

  • 比賽(考試)時,寫了一個自以為正確的程式,但是還是不放心,可以再寫一個暴力程式,對拍驗證。
  • 做題做到天昏地暗,頭暈目眩,不分東南西北之時,眼前一片血紅,於是不小心偷了一個充滿生命力的程式碼,再寫個資料生成器,說不定對拍能挽救程式碼的生命。

例題

A+B Problem

資料生成器

方法

生成隨機數之必備武器:ctimecstdlib。 在main開頭寫:

srand((unsigned)time(NULL));

意思大概是設定隨機數的種子為你的時間。 如果你不寫或者寫個srand(1234567),你發現你每次生成的“隨機數”都是一樣的。

然後使用:

int x=rand();

就可以得到一個00到不知道多少(RAND_MAX)的整數。 如果你想得到得到[a,b][a,b]之間的一個整數:

int x=rand()%(b-a+1)+a;

如果a,ba,b有些大,可以這樣,以防資料太弱:

int x=1ll
*rand()*rand()%(b-a+1)+a;

如果想得到浮點數,除以1010即可。

當然,如果想要生成一個樹、一個連通圖、一個二分圖什麼的,加點資料結構之類的就行了曾經我為了對拍一個破圈法的題,寫了100多行的資料生成器。

程式碼

#include<ctime>
#include<cstdio>
#include<cstdlib>

#define MAXN 1000

int main(){
    srand((unsigned)time(NULL));
    int A,B;
    A=rand()%MAXN;
    B=rand()%MAXN;
printf("%d %d\n",A,B); //想像一下用手輸資料的時候不打換行會怎麼樣,這裡就會怎麼樣 }

你的程式 == WA

什麼都不用加,找的你的程式的exe檔案即可。

#include<cstdio>

int main(){
    int a,b;
    scanf("%d%d",&a,&b);
    printf("%d",a/b*b+b);
}

我的程式 == AC

什麼都不用加,偷到我的程式的exe檔案即可。 沒有時間了,只好先水一個SPFA,如有錯請見諒 。

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

#define MAXM 2
#define MAXN 3
struct Edge{
    int v,w;
    Edge *Next;
}E[MAXM+5];
Edge *ecnt,*First[MAXN+5];

void Init(){
    ecnt=&E[0];
    memset(First,0,sizeof First);
}

void AddEdge(int u,int v,int w){
    ++ecnt;
    ecnt->v=v,ecnt->w=w;
    ecnt->Next=First[u],First[u]=ecnt;
}

int dist[MAXN+5];
bool vis[MAXN+5];
int SPFA(int S,int T){
    memset(vis,0,sizeof vis);
    memset(dist,0x3f,sizeof dist);
    queue<int> Q;Q.push(S);
    dist[S]=0,vis[S]=1;
    while(!Q.empty()){
        int u=Q.front();
        Q.pop();vis[u]=0;
        for(Edge *i=First[u];i!=NULL;i=i->Next){
            int v=i->v,w=i->w;
            if(dist[v]>dist[u]+w){
                dist[v]=dist[u]+w;
                if(!vis[v]){
                    vis[v]=1;
                    Q.push(v);
                }
            }
        }
    }
    return dist[T]==0x3f3f3f3f?-1:dist[T];
}

int main(){
    int a,b;
    scanf("%d%d",&a,&b);
    Init();
    AddEdge(1,2,a);
    AddEdge(2,3,b);
    printf("%d",SPFA(1,3));
}

AC證明: AC證明

對拍程式

其實我的續集只是續的這個部分。 古文《對拍》中,是使用的C++寫對拍,各位是不是感覺很慢?看上去很不爽?還要編譯? 所以現在使用bat檔案完成對拍,Windows下有一個命令:fc,可以比較兩個檔案。

準備活動

方法:

  • 在一個你喜歡的位置新建一個記事本檔案dp.txt
  • 將字尾.txt改成.bat,所以你的檔案變成了dp.bat

這個時候問題來了: 我的檔案是這樣的嚶嚶嚶: 沒有後綴的情況 這樣做: 隨意開啟一個資料夾\to(左上角)組織\to資料夾和搜尋選項\to(上方)檢視\to下面的高階設定中找到“隱藏已知檔案型別的副檔名”,把前面的勾去掉即可。 顯示副檔名的方法(1)

顯示副檔名的方法(2) 然後你就會發現變成了這樣: 副檔名出現了.txt改成.bat副檔名為bat

程式碼

繼續:

  • 右鍵dp.bat,點選“編輯”

接下來才是重點。 仔細觀察你即將貼上進去的程式碼:

@echo off
:loop
	資料生成器位置 > data.txt
	你的程式的位置 < data.txt > yours.txt
	我的程式的位置 < data.txt > mine.txt
	fc yours.txt mine.txt
	if not errorlevel 1 goto loop
pause
goto loop

你急用就直接粘過去,如果你希望考試的時候能用就繼續看。

示例

@echo off
:loop
	C:\3\bin\Debug\3.exe > data.txt
	C:\1\bin\Debug\1.exe < data.txt > yours.txt
	C:\2\bin\Debug\2.exe < data.txt > mine.txt
	fc yours.txt mine.txt
	if not errorlevel 1 goto loop
pause
goto loop

注意一定要填exe檔案。 4個檔案的示例 把上面的程式碼儲存後,直接雙擊dp.bat一次對拍 你一定看懂了它的意思。 這時開啟data.txt,裡面是你的資料生成器生成的資料,yours.txtmine.txt分別是你的輸出結果和我的輸出結果。

當然,你可以“按任意鍵繼續”。 如果輸出一樣是什麼效果請自行試驗。

更多內容

這裡個人是對對拍程式碼的解讀,更準確的內容請百度。

  • @echo off:此句可不要,但會多輸出一些提示性語句。echo有回聲的意思,應該是指回顯,而off就是關閉。至於為什麼fc的回顯沒有關閉,不知道= =
  • :loopgoto loop:等於C++loop:goto loop,相當於迴圈。
  • <>:大概是執行後輸入輸出之意。
  • fc FILE1 FILE2:比較FILE1FILE2
  • if not errorlevel 1:大概是看fc的“返回值”,判斷兩檔案是否相同。
  • pause:按任意鍵繼續

以上語句全部可以通過C++system函式執行,效果相同。

後記

感謝你閱讀到了這裡(可能你是一下子拉到底的),本文確實廢話較多,但是之前的《對拍》有些內容確實不太優秀,我又不忍心刪掉它,所以寫了這樣一篇。