語法書 / AA 競程語法書 上冊 / 第五單元 / 全部判定結果詳解

5.3 全部判定結果詳解

程式上傳後,OJ 會給你一個判定結果。如果沒通過,這個結果能告訴你大概是哪裡出問題。理解每個結果,才能有效地除錯。

7 大判定結果

AC —— Accepted(接受)

代表什麼:你的程式對所有隱藏測資都答對了。

你該做的:恭喜!移到下一題。


WA —— Wrong Answer(答案錯誤)

代表什麼:程式編譯和執行都成功了,但對某筆測資的輸出和預期答案不一致。

常見原因

  • 演算法邏輯錯誤(核心問題解法本身有 bug)
  • 讀題不仔細(例如沒注意輸入格式或範圍)
  • 浮點數精度不足(算出來是 3.9999999 而不是 4.0)
  • 值其實全對、只是空白或換行不同——在沒有 PE 判定的 OJ 上,這種情況會直接顯示成 WA(見下面的 PE)
  • 邊界情況沒處理(0、負數、最大值、最小值等)

除錯方法

  1. 重新檢查演算法邏輯
  2. 用範例輸入在自己電腦上跑一遍,看結果對不對
  3. 檢查輸出格式是否完全符合題目要求
  4. 考慮有沒有遺漏的邊界情況

PE —— Presentation Error(格式錯誤)

代表什麼:輸出的「值」全部正確,只有空白或換行的排法和標準答案不同——例如行末多了空白、少了最後的換行。

其實 PE 就是 WA 的一種特殊情況:計分上和 WA 完全一樣(該筆測資 0 分),差別只在系統多告訴你一件事——「把空白差異忽略掉的話,你的答案就對了」。所以看到 PE 反而可以鬆一口氣:解法不用動,專心修輸出格式就好。

常見原因

  • 行末多印了空白(例如同一行輸出多個數字時,最後一個數字後面也補了空白)
  • 少了最後的換行
  • 該分行的輸出印在同一行、或該同一行的輸出分了行

除錯方法

  1. 對照題目的範例輸出,逐字元檢查——特別是每行結尾和最後一行
  2. 同一行輸出多個值時,用 5.1 的「不是第一個,就先補一個空白」寫法
  3. 確認最後一行結尾有印出換行

RE —— Runtime Error(執行時錯誤)

代表什麼:程式編譯通過了,但執行時遇到了致命錯誤,導致程式崩潰。(在 AACPOJ 上,這個判定顯示為 RTE,是同一件事。)

常見原因

  • 陣列存取越界int arr[10]; arr[15] = 5;(初學者最常見的原因)
  • 除以零int x = 10 / 0;
  • 陣列開太大:一次宣告一個非常大的陣列,程式可能直接崩潰

除錯方法

  1. 檢查陣列索引有沒有超出範圍(最常見)
  2. 檢查所有除法,確保分母不會是零
  3. 檢查有沒有宣告超大的陣列

CE —— Compilation Error(編譯錯誤)

代表什麼:程式碼語法不正確,編譯器無法編譯。

常見原因

  • #include 遺漏:用了 vector 卻沒 #include <vector>
  • 語法錯誤:少了分號、括號不配對、關鍵字拼錯
  • 函式/型別名稱不存在:用了沒定義的變數或函式
  • 命名空間衝突:沒加 using namespace std; 就用 cout,或者變數名和標準函式庫衝撞

除錯方法

  1. 在自己的編譯器上編譯,看編譯訊息
  2. 仔細讀編譯錯誤訊息,它通常會指出第幾行
  3. 檢查所有 #include 是否完整
  4. 檢查 using namespace std; 是否存在(或改用完整名稱如 std::cout

CE Debug 手冊

編譯錯誤 可能原因 檢查項目
error: 'vector' is not a member of 'std' 沒有 #include <vector> 加上 #include <vector>
error: 'cout' was not declared 沒有 using namespace std; 或沒 #include <iostream> 加上兩行
error: expected ';' before '...' 語句後面少了分號 檢查該行末尾

正式檢測或比賽時,CE 代表程式根本沒有成功編譯,後面的測試也無法進行。平常就要熟悉常見編譯錯誤訊息,避免因為少打標頭檔、分號或打錯變數名稱而失分。


TLE —— Time Limit Exceeded(超時)

代表什麼:程式編譯和執行都成功,但花的時間超過了題目規定的時間限制。

常見原因

  • 做太多次運算:例如三層、四層迴圈疊在一起,n 一大、總次數就爆炸成長而超時
  • 無意中死迴圈:條件永遠不成立,迴圈一直跑
  • 重複計算太多次:同一個東西算了很多遍,沒有把算過的結果留下來重複利用

除錯方法

  1. 看程式跑幾層迴圈:一層?兩層?巢狀越多層,總次數增加得越快
  2. 估計執行次數:看題目限制(如 n \le 10^6),計算最多要做多少次操作
    • 通常 1 秒內可以做 10^9 次簡單操作(加減、比較、賦值等)
    • 如果時間限制是 2 秒,可以做 2 \times 10^9
  3. 想更快的做法:如果次數估起來太多,代表要換一個更聰明的演算法——這是競程最核心的功夫,後面的課程會慢慢學

MLE —— Memory Limit Exceeded(記憶體超限)

代表什麼:程式使用的記憶體超過了題目規定的上限。

常見原因

  • 陣列開太大int arr[10000000][10000000]; 一開就要 TB 級別記憶體
  • 開了很多個大陣列:好幾個大陣列加起來,也可能超過限制

除錯方法

  1. 計算陣列大小:一個 int 是 4 bytes,10^6 個就是 4 MB
    • 題目如果限制 64 MB,最多能開 16 \times 10^6int
    • 如果要開 2D 陣列,記憶體是「長 × 寬」相乘,很容易爆掉,要特別小心
  2. 只開需要的大小:不要習慣性把陣列開到最大,照題目給的範圍開就好

記憶體限制通常比時間限制不容易踩到,但不能完全忽略。看到題目給的記憶體限制時,還是要估算大型陣列、二維陣列或多份資料結構會不會超過限制。