当前位置: 首页 > 資訊 >

10 手把手帶你從 OJ 練題 (Zero Judge)

相信很多新手在第一次聽到老手建議去不同的線上評測平台「刷題目」時,總會一頭霧水的不知道要怎麼練習,因此想各位展示要如何從 0 到 1 在 Online Judge 上寫出第一個題目!

本來想要用在ZeroJudge的第一個題目當作示範,但想到本系列文章是 APCS,因此題目決定是目前在 ZeroJudge 公布的最後一次實作題的第一題「g275: 1. 七言對聯」。(感謝 cthbst 提供測試資料及上傳 ZOJ)

https://ithelp.ithome.com.tw/upload/images/20210924/20103852QAfkaKB0SP.png

  1. 先讀懂題目

每一個題目基本上會有「題目敘述」、「輸入輸出說明」、「範例測試資料」及「配分機制」四大部分,但當看到任何一個題目時,不要先看輸入或輸出,雖然可以藉由輸入輸出猜出原題目的題意,但不要本末倒置變成會錯題意的窘境。

題目敘述
中文依照發音方式可以分為平聲與仄聲,假設我們把平聲標記為 0 而仄聲標記為 1
一個七言對聯包含兩個句子,每個句子包含恰好七個字

七言對聯有三個限制:
A: 二四不同二六同:每一句第二、四個字必須不同平仄,而第二、六個字必須相同平仄
B: 仄起平收:第一句的結尾必須為仄聲,第二句的結尾必須為平聲
C: 上下相對:第一、二句的第二、四、六個字平仄必須不同

給你 n 組對聯,分別用0, 1 代表平仄,請輸出它違反了哪幾條規則
若以上規則皆無違反,請輸出None

是個只要有國文平仄基礎就能懂的題目呢

  1. 確認輸入輸出

在輸入及輸出部分,不同題目會有不同的形態,有時需要特別注意。在這題的輸入輸出都很容易理解,若有解釋不清楚的部分可以參考題目給的範例輸入/輸出。

輸入說明
輸入一個正整數 n (1≤n≤30) 代表對聯數量,接下來有 2n 行,每行有 7 個數字,數字不是 0 就是 1

輸出說明
對於每個對聯,輸出一行表示它違反了哪些規則,若三個規則都遵守則輸出 None

  1. 透過給分機制當作參考想出解法

在比較困難的題目中,題目會給出一些
因為本題沒有任何的給分機制,所以沒有任何的參考。但因為這題的解法夠直覺也夠簡單,因此只需要照著題目實作,分別判斷 ABC 三個條件,在全符合的時候輸出 None,而當有任何一個部分不符合時則是印出不符合的字母(記得每做一次都要換行)。

  1. 準備好寫程式的環境(IDE, 編輯器+編譯器...)

雖然我現在的電腦沒有裝任何 Linux 的虛擬機器,如果想要熟悉考試環境的話建議還是建議多使用熟悉喔。我自己的開發環境比較習慣使用 Terminal,而編輯器則是 vim 和 VSCode 為主。秀出桌面好害羞(/////

https://ithelp.ithome.com.tw/upload/images/20210924/20103852orKPIAZiM8.png

  1. 解題!

在確定是否合法的部分,我分別寫了三個不同函式去判定 ABC 分別是否合法。

bool isA(const int c[2][7]) {
	for(int i = 0; i < 2; ++i)
		if(c[i][1] == c[i][3] || c[i][1] != c[i][5]) return false;
	return true;
}

bool isB(const int c[2][7]){
	return (c[0][6] == 1 && c[1][6] == 0);
}

bool isC(const int c[2][7]){
	for(int i = 1; i <= 5; i += 2)
		if(c[0][i] == c[1][i]) return false;
	return true;
}

在主程式的部分則是依照提議創出能夠容納兩個平仄的二維 int 矩陣 (也可以用bool),並創造出三個 bool 分別儲存三個規定的合法性,再依照題意輸出,最後整個程式再用輸入筆數 (n) 包起來。

int main(){
	int n;
	cin >> n;
	while(n--){
		int couplet[2][7];
		for(int i = 0; i < 2; ++i)
			for(int j = 0; j < 7; ++j)
				cin >> couplet[i][j];
		bool a = isA(couplet), b = isB(couplet), c = isC(couplet);
		if(a && b && c)
			cout << "None\n";
		else
			cout << (a?"":"A") << (b?"":"B") << (c?"":"C") << "\n";
	}

	return 0;
}
  1. 利用測試資料測試 & 繳交

除了題目給的測試資料外,也要根據題目給的範圍創造出有可能會需要檢查的測試資料。

SkyHong$ ./deafult.out
2
0 1 1 0 0 0 1
1 0 1 1 0 1 1
0 1 0 0 0 0 1
0 0 0 0 0 1 1

AB
ABC

確定沒錯後上傳到 Zero Judge,最後 Accept 了!

https://ithelp.ithome.com.tw/upload/images/20210924/20103852ljUEFxSRz9.png


當題目寫完後,可以把自己寫的程式整理起來,或是可以放在自己的部落格,再放上寫題目時遇到的瓶頸、學到的東西和要注意的地方。當寫題目的量一點一點的變多時,成就感也會越來越高,也會越來越有自信喔!加油!