5.3 全部判定結果詳解
程式上傳後,OJ 會給你一個判定結果。如果沒通過,這個結果能告訴你大概是哪裡出問題。理解每個結果,才能有效地除錯。
¶7 大判定結果
¶AC —— Accepted(接受)
代表什麼:你的程式對所有隱藏測資都答對了。
你該做的:恭喜!移到下一題。
¶WA —— Wrong Answer(答案錯誤)
代表什麼:程式編譯和執行都成功了,但對某筆測資的輸出和預期答案不一致。
常見原因:
- 演算法邏輯錯誤(核心問題解法本身有 bug)
- 讀題不仔細(例如沒注意輸入格式或範圍)
- 浮點數精度不足(算出來是 3.9999999 而不是 4.0)
- 值其實全對、只是空白或換行不同——在沒有 PE 判定的 OJ 上,這種情況會直接顯示成 WA(見下面的 PE)
- 邊界情況沒處理(0、負數、最大值、最小值等)
除錯方法:
- 重新檢查演算法邏輯
- 用範例輸入在自己電腦上跑一遍,看結果對不對
- 檢查輸出格式是否完全符合題目要求
- 考慮有沒有遺漏的邊界情況
¶PE —— Presentation Error(格式錯誤)
代表什麼:輸出的「值」全部正確,只有空白或換行的排法和標準答案不同——例如行末多了空白、少了最後的換行。
其實 PE 就是 WA 的一種特殊情況:計分上和 WA 完全一樣(該筆測資 0 分),差別只在系統多告訴你一件事——「把空白差異忽略掉的話,你的答案就對了」。所以看到 PE 反而可以鬆一口氣:解法不用動,專心修輸出格式就好。
常見原因:
- 行末多印了空白(例如同一行輸出多個數字時,最後一個數字後面也補了空白)
- 少了最後的換行
- 該分行的輸出印在同一行、或該同一行的輸出分了行
除錯方法:
- 對照題目的範例輸出,逐字元檢查——特別是每行結尾和最後一行
- 同一行輸出多個值時,用 5.1 的「不是第一個,就先補一個空白」寫法
- 確認最後一行結尾有印出換行
¶RE —— Runtime Error(執行時錯誤)
代表什麼:程式編譯通過了,但執行時遇到了致命錯誤,導致程式崩潰。(在 AACPOJ 上,這個判定顯示為 RTE,是同一件事。)
常見原因:
- 陣列存取越界:
int arr[10]; arr[15] = 5;(初學者最常見的原因) - 除以零:
int x = 10 / 0; - 陣列開太大:一次宣告一個非常大的陣列,程式可能直接崩潰
除錯方法:
- 檢查陣列索引有沒有超出範圍(最常見)
- 檢查所有除法,確保分母不會是零
- 檢查有沒有宣告超大的陣列
¶CE —— Compilation Error(編譯錯誤)
代表什麼:程式碼語法不正確,編譯器無法編譯。
常見原因:
- #include 遺漏:用了
vector卻沒#include <vector> - 語法錯誤:少了分號、括號不配對、關鍵字拼錯
- 函式/型別名稱不存在:用了沒定義的變數或函式
- 命名空間衝突:沒加
using namespace std;就用cout,或者變數名和標準函式庫衝撞
除錯方法:
- 在自己的編譯器上編譯,看編譯訊息
- 仔細讀編譯錯誤訊息,它通常會指出第幾行
- 檢查所有
#include是否完整 - 檢查
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 一大、總次數就爆炸成長而超時
- 無意中死迴圈:條件永遠不成立,迴圈一直跑
- 重複計算太多次:同一個東西算了很多遍,沒有把算過的結果留下來重複利用
除錯方法:
- 看程式跑幾層迴圈:一層?兩層?巢狀越多層,總次數增加得越快
- 估計執行次數:看題目限制(如 n \le 10^6),計算最多要做多少次操作
- 通常 1 秒內可以做 10^9 次簡單操作(加減、比較、賦值等)
- 如果時間限制是 2 秒,可以做 2 \times 10^9 次
- 想更快的做法:如果次數估起來太多,代表要換一個更聰明的演算法——這是競程最核心的功夫,後面的課程會慢慢學
¶MLE —— Memory Limit Exceeded(記憶體超限)
代表什麼:程式使用的記憶體超過了題目規定的上限。
常見原因:
- 陣列開太大:
int arr[10000000][10000000];一開就要 TB 級別記憶體 - 開了很多個大陣列:好幾個大陣列加起來,也可能超過限制
除錯方法:
- 計算陣列大小:一個
int是 4 bytes,10^6 個就是 4 MB- 題目如果限制 64 MB,最多能開 16 \times 10^6 個
int - 如果要開 2D 陣列,記憶體是「長 × 寬」相乘,很容易爆掉,要特別小心
- 題目如果限制 64 MB,最多能開 16 \times 10^6 個
- 只開需要的大小:不要習慣性把陣列開到最大,照題目給的範圍開就好
記憶體限制通常比時間限制不容易踩到,但不能完全忽略。看到題目給的記憶體限制時,還是要估算大型陣列、二維陣列或多份資料結構會不會超過限制。