【NOIP復賽篇4】ACM/OI 對拍程序的寫法


先聲明,本文章轉載至:http://blog.csdn.net/wlx65003/article/details/51149196

搞程序設計競賽的同學很多時候都會因為WA但苦苦找不到錯誤數據而苦惱,雖然肉眼debug的能力也很重要,但有的時候一直手打數據測試兩三天也沒有必要。這里就介紹一種對拍程序的寫法,是我改進過的,自認為效率應該是比較高了。

如果你懶得學實現細節了,想直接使用,那么下面的內容可以略過了,到這去下載打包好的,里面有使用教程:

http://pan.baidu.com/s/1boERyGZ

實現細節

首先對拍程序,顧名思義,一個輸入給兩個程序分別跑一遍,看看對不對的上。

那么牽扯到三個步驟:

  1. 生成一組輸入數據
  2. 把這組數據分別給兩個程序運行,并生成兩組輸出數據
  3. 比較兩組輸出數據

看到這個步驟很多人應該已經有想法了,沒錯用文件操作能實現,但太麻煩,因為你得修改你自己的代碼把輸出重定向到一個文件,這要是一不小心忘記刪重定向直接交了又得WA一遍233(不對,是RE),這里介紹一種更方便更高逼格的批處理命令。

首先新建一個批處理文件,命名為簡易對拍程序.bat,什么你不知道怎么新建?右鍵新建一個文本文檔直接把后綴名改成bat就好啦,因為批處理文件本質上就是一堆命令文本嘛。

然后右鍵—編輯,開始打代碼:

首先第一步:生成一組輸入數據。

我們假設你已經寫好了一個數據生成器,編譯成rand.exe并放在當前目錄下了,那么我們只要把這個程序的輸入重定向到一個文件就行了,如果你直接在源碼里操作,還得各種文件流重定向煩得要死。在批處理命令里很簡單,就一句話:

rand.exe > in.txt

是不是很簡單明了?

那怎么把文件輸入到一個程序里去呢?沒錯:

my.exe < in.txt
std.exe < in.txt

my.exe是你寫的錯誤程序,std.exe是標程

那怎么把兩個程序的輸出再重定向到文件里去呢?也很簡單:

my.exe < in.txt > myout.txt
std.exe < in.txt > stdout.txt

是不是相當方便?

接下來就是比較myout.txt和stdout.txt了,也不用你手寫判斷程序,windows自帶一個比較命令:fc(file compare)

fc myout.txt stdout.txt

如果兩個沒有差異,會顯示:找不到差異,否則會顯示不同的附近的幾行的文本。

匯總一下:

rand.exe > in.txt
my.exe < in.txt > myout.txt
std.exe < in.txt > stdout.txt
fc myout.txt stdout.txt

好,這樣一個簡易版對拍程序就寫好了。但這個功能也太簡陋了,只能對拍一次,要是數據難找點豈不是要你運行到手酸?

有人就問了,能不能循環?答案是:可以!

@echo off  
:loop  
    rand.exe > in.txt
    my.exe < in.txt > myout.txt
    std.exe < in.txt > stdout.txt
    fc myout.txt stdout.txt
if not errorlevel 1 goto loop  
pause
goto loop

別懵逼,一行行給你解釋。

首先@echo off

是關掉輸入顯示,不然你的所有命令都會顯示出來的,防止刷屏。

:loop是定位標記點,和c語言里的goto很像。

中間是主體程序。

if not errorlevel 1 goto loop

,errorlevel

是上一個命令的返回值,fc在文件不同時返回1,相同時返回0,這一行的意思就是,如果fc返回的不是1,就跳到:loop,使勁循環。

pause,暫停,一旦fc返回1,就會執行到這一行,停住程序,給你時間看數據。

goto loop,看完數據,按下任意鍵結束暫停,繼續循環。

這樣一來功能就頓時強大起來了,為了紀念這么偉大的改進,我們把文件名重命名為普通版對拍程序.bat。(網上流傳的也大多就這個版本了)

但這還不夠! 為什么? 我們看一下rand程序的寫法。

例如題目格式是,T組數據,每組數據一個n,一個m,然后n個1~m的整數

你就這么寫:

#include<bits/stdc++.h>
using namespace std;
#define random(a,b) ((a)+rand()%((b)-(a)+1))

int main( int argc, char *argv[] )
{ 
    int seed=time(NULL);
    srand(seed);

    printf("1\n");
    int n=10;
    int m=random(1,20);
    printf("%d %d\n",n,m);
    for(int i=0 ; i<n ; ++i)
    {
        printf(" %d ",random(0,m));
    }
    printf("\n");
    return 0;
}

這樣的話有個缺點,time(NULL)

是一秒才更新一次的,也就是說我們的隨機數據一秒才換一次,太慢了!

有沒有什么變的更快的隨機數種子?有!windows自帶了一個隨機數發生器:%random%,它的值就是一個隨機整數,可以在命令行里調用。

那接下來就好辦了,我們把這個數傳給rand.exe用來當隨機數種子就行了。

什么?你不知道怎么傳?

呃,你知不知道main函數里這兩個參數干嘛用的:int argc, char *argv[]?

恐怕好多人還不知道,我這里解釋下,這兩個就是傳入參數,argc

是參數個數,*argv[]

是參數表,從1開始。

知道了這個就好辦了。

@echo off  
:loop  
    rand.exe %random% > data.in
    std.exe < data.in > std.out
    my.exe < data.in > my.out
    fc my.out std.out 
if not errorlevel 1 goto loop  
pause
goto loop

我們把%random%當參數傳給rand.exe就行了。

然后程序里這么寫:

#include<bits/stdc++.h>
using namespace std;
#define random(a,b) ((a)+rand()%((b)-(a)+1))

stringstream ss;

int main( int argc, char *argv[] )
{ 
    int seed=time(NULL);
    if(argc)//如果有參數
    {
        ss.clear();
        ss<<argv[1];
        ss>>seed;//把參數轉換成整數賦值給seed
    }
    srand(seed);
    //以上為隨機數初始化,請勿修改
    //random(a,b)生成[a,b]的隨機整數

    //以下寫你自己的數據生成代碼 
    printf("1\n");
    int n=10;
    int m=random(1,20);
    printf("%d %d\n",n,m);
    for(int i=0 ; i<n ; ++i)
    {
        printf(" %d ",random(0,m));
    }
    printf("\n");
    return 0;
}

我這里用stringstream把字符串轉換成整數,你們也可以用其他辦法。

這么一來,數據測試效率就得到了上千倍的提升!為了紀念這么偉大的改進,我們把程序重命名為狂拽酷炫吊炸天對拍程序.bat

這么一來對拍程序就徹底完成啦!完結撒花!

你只需把my.cpp和std.cpp放在和對拍程序相同的目錄下

my.cpp里放你自己的代碼,編譯成my.exe

std.cpp里放標程,編譯成std.exe

(推薦用dev-c++,單文件編譯方便)

然后雙擊運行對拍程序,等待它暫停,然后打開data.in就能看到對拍出來的數據啦~

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,646評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,595評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,560評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,814評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,224評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,444評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,988評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,804評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,998評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,237評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,706評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,993評論 2 374

推薦閱讀更多精彩內容