ACM入門前必看的OJ
所謂OJ,顧名思義Online Judge,一個使用者提交的程式在Online Judge系統下執行時將受到比較嚴格的限制,包括執行時間限制,記憶體使用限制和安全限制等。使用者程式執行的結果將被Online Judge系統捕捉並儲存,然後再轉交給一個裁判程式。該裁判程式或者比較使用者程式的輸出資料和標準輸出樣例的差別,或者檢驗使用者程式的輸出資料是否滿足一定的邏輯條件。最後系統返回給使用者一個狀態:通過(Accepted,AC)、答案錯誤(Wrong Answer,WA)、超時(Time Limit Exceed,TLE)、超過輸出限制(Output Limit Exceed,OLE)、超記憶體(Memory Limit Exceed,MLE)、執行時錯誤(Runtime Error,RE)、格式錯誤(Presentation Error,PE)、或是無法編譯(Compile Error,CE),並返回程式使用的記憶體、執行時間等資訊。
可能看完定義還不太熟悉OJ,推薦杭電ACM1000,我們可以通過練習來鞏固我們對OJ的輸入輸出掌握程度。
杭電ACM官網:http://acm.hdu.edu.cn/
那麼接下來是關於OJ的判定:
在開始做OJ時,會面臨一個輸入輸出資料的問題,OJ裡的輸入輸出資料和平時的寫程式不大一樣。為什 麼會不一樣呢,這就牽涉到評測系統怎麼判斷你提交的程式是正確的。實際上評測系統是把程式的標準輸入輸 出資料都是放在文字檔案裡,你提交的程式會先經過編譯,然後執行,從輸入檔案中讀取資料,然後把結果輸 出到一個文字檔案中,評測系統再把標準的輸出檔案和你提交的程式執行的結果的輸出檔案進行對比,從而判 斷你提交的程式的正確與否。既然是這樣,要判斷提交的程式的正確性就依賴於系統的測試資料,這時就不可 能只是用一組測試資料來判斷程式的正確性,需要有很多組測試資料,而國際程式設計競賽標準的評測系統是 PC2,它只支援一個題目一個輸入資料檔案、一個輸出資料檔案。所以這時候就得把多組測試資料放在一個文 件裡,提交的程式必須把這個檔案裡的多組輸入資料都得出結果。
一、輸入: 1、只有一組測試資料,這時候是最簡單的了。 C語言程式碼:
#include < stdio.h > int main() { int a,b; scanf("%d %d",&a, &b); printf("%d\n",a+b); return0; }
C++語言程式碼:
1 #include < iostream > 2 usingnamespace std; 3 int main() 4 { 5 int a,b; 6 cin >> a >> b; 7 cout << a+b << endl;8 return0; 9 }
2、有多組測試資料,直到讀至輸入檔案結尾為止,這時需要用到while(scanf("%d",&n)!=EOF)或while (cin>>n)。
C語言程式碼:
1 #include < stdio.h > 2 int main() 3 { 4 int a,b; 5 while(scanf("%d %d",&a, &b) != EOF) 6 printf("%d\n",a+b); 7 return0; 8 }
說明:scanf函式返回值就是讀出的變數個數,如:scanf( “%d %d”, &a, &b );如果只有一個整數輸入,返 回值是1,如果有兩個整數輸入,返回值是2,如果一個都沒有,則返回值是-1。EOF是一個預定義的常量,等
於-1。
C++語言程式碼:
1 #include < iostream > 2 usingnamespace std; 3 int main() 4 { 5 int a,b; 6 while(cin >> a >> b) 7 cout << a+b << endl; 8 return0; 9 }
3、在開始的時候輸入一個N,接下來是N組資料。 C語言程式碼:
1 #include<stdio.h> 2 int main() 3 { 4 int n,i; 5 int a,b; 6 scanf("%d",&n); 7 for(i=0;i<n;i++) 8 { 9 scanf("%d%d",&a,&b); 10 printf("%d\n",a+b); 11 } 12 return0; 13 }
或者
1 #include<stdio.h> 2 int main() 3 { 4 int n, i; 5 int a, b; 6 scanf("%d", &n); 7 while (n--) 8 { 9 scanf("%d%d", &a, &b); 10 printf("%d\n", a + b); 11 } 12 return0; 13 }
C++程式碼:
1 #include <iostream> usingnamespace std; 2 int main() 3 { 4 int a, b, n; 5 cin >> n; 6 while (n--) 7 { 8 cout << a + b << endl; 9 } 10 return0; 11 }
4、 輸入不說明有多少組資料,但以某個特殊輸入為結束標誌。如以0 0 代表輸入結束。 C語言程式碼:
#include <stdio.h> int main() { int a,b; while(scanf("%d %d",&a, &b) &&(a||b)) printf("%d\n",a+b); }
C++語言程式碼:
1 #include<iostream> 2 usingnamespace std; 3 int main() 4 { 5 int a ,b; 6 while(cin>>a>>b&&(a||b)) 7 { 8 cout<<a+b<<endl; 9 } 10 return0; 11 }
5、還有一種是前幾種的組合。 C語言程式碼:
1 #include<stdio.h> 2 int main() 3 { 4 int n,sum,a; 5 while(scanf("%d",&n) && n) 6 { 7 sum=0; 8 while(n--) 9 { 10 scanf("%d",&a); 11 sum+=a; 12 } 13 printf("%d\n",sum); 14 return 0; 15 }
C++語言程式碼:
1 #include<iostream> 2 usingnamespace std; 3 int main() 4 { 5 int n,sum,a; 6 while(cin>>n&&n) 7 { 8 sum=0; 9 while(n--) 10 { 11 cin>>a; 12 sum+=a; 13 } 14 cout<<sum<<endl; 15 } 16 return0; 17 }
輸入是一整行的字串的,C語法:
char buf[20];
gets(buf);
如果用string buf;來儲存:
getline( cin , buf );
如果用char buf[ 255 ]; 來儲存:
cin.getline( buf, 255 );
scanf(“ %s%s”,str1,str2),在多個字串之間用一個或多個空格分隔;
若使用gets函式,應為gets(str1); gets(str2); 字串之間用回車符作分隔。
通常情況下,接受短字元用scanf函式,接受長字元用gets函式。
而getchar函式每次只接受一個字元,經常c=getchar()這樣來使用。
getline 是一個函式,它可以接受使用者的輸入的字元,直到已達指定個數,或者使用者輸入了特定的字元。它
的函式宣告形式(函式原型)如下:
istream& getline(char line[], int size, char endchar = '\n');
不用管它的返回型別,來關心它的三個引數
char line[]: 就是一個字元陣列,使用者輸入的內容將存入在該陣列內。
int size : 最多接受幾個字元?使用者超過size的輸入都將不被接受。
char endchar :當用戶輸入endchar指定的字元時,自動結束。預設是回車符。
結合後兩個引數,getline可以方便地實現:使用者最多輸入指定個數的字元,如果超過,則僅指定個數的前面 字元有效,如果沒有超過,則使用者可以通過回車來結束輸入。
char name[4];cin.getline(name,4,'\n');
由於 endchar 預設已經是 '\n',所以後面那行也可以寫成:
cin.getline(name,4);
最後需要說明的是,C++的輸入輸出流用起來比較方便,但速度比C要慢得多。在輸入輸出量巨大時,用 C++很可能超時,應採用C的輸入輸出。