5.3 全部判定結果詳解
程式上傳後,OJ 會給你一個判定結果。如果沒通過,這個結果能告訴你大概是哪裡出問題。理解每個結果,才能有效地除錯。
¶6 大判定結果
¶AC —— Accepted(接受)
代表什麼:你的程式對所有隱藏測資都答對了。
你該做的:恭喜!移到下一題。
¶WA —— Wrong Answer(答案錯誤)
代表什麼:程式編譯和執行都成功了,但對某筆測資的輸出和預期答案不一致。
常見原因:
- 演算法邏輯錯誤(核心問題解法本身有 bug)
- 讀題不仔細(例如沒注意輸入格式或範圍)
- 浮點數精度不足(算出來是 3.9999999 而不是 4.0)
- 輸出格式不符(多了空格、少了換行等)
- 邊界情況沒處理(0、負數、最大值、最小值等)
除錯方法:
- 重新檢查演算法邏輯
- 用範例輸入在自己電腦上跑一遍,看結果對不對
- 檢查輸出格式是否完全符合題目要求
- 考慮有沒有遺漏的邊界情況
¶RE —— Runtime Error(執行時錯誤)
代表什麼:程式編譯通過了,但執行時遇到了致命錯誤,導致程式崩潰。
常見原因:
- 除以零:
int x = 10 / 0; - 陣列存取越界:
int arr[10]; arr[15] = 5; - 指標非法存取:
int* p = nullptr; *p = 10; - 堆疊溢位:遞迴太深或陣列定義太大
- 非法記憶體釋放:
delete同一個指標兩次
除錯方法:
- 檢查所有除法操作,確保分母不為零
- 檢查陣列索引是否在範圍內
- 檢查遞迴深度是否過大
- 檢查動態記憶體分配是否正確
¶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 '...' |
語句後面少了分號 | 檢查該行末尾 |
error: request for member '...' in something not a struct |
用了 . 來存取指標成員 |
改用 -> 或先解參考 |
¶TLE —— Time Limit Exceeded(超時)
代表什麼:程式編譯和執行都成功,但花的時間超過了題目規定的時間限制。
常見原因:
- 演算法複雜度太高:O(n^3) 或 O(2^n),當 n 很大時會超時
- 無意中死迴圈:條件永遠不成立,迴圈一直跑
- 重複計算太多次:沒有用記憶化或快取
- IO 操作太多:逐個讀/寫,沒有優化
除錯方法:
- 分析複雜度:算一下你的演算法大概是 O(n)、O(n \log n) 還是 O(n^2)
- 估計執行次數:看題目限制(如 n \le 10^6),計算演算法最多要做多少次操作
- 通常 1 秒內可以做 10^8 次簡單操作(加減乘除、賦值等)
- 如果時間限制是 2 秒,可以做 2 \times 10^8 次
- 優化演算法:改用更快的演算法,或加上記憶化
- 優化 IO:改用
scanf/printf或加上ios::sync_with_stdio(false)
TLE 優化技巧:
// 優化 IO(加在 main 開頭)
ios::sync_with_stdio(false);
cin.tie(nullptr);
// 或改用更快的 scanf/printf
int n;
scanf("%d", &n);
printf("%d\n", result);
¶MLE —— Memory Limit Exceeded(記憶體超限)
代表什麼:程式使用的記憶體超過了題目規定的上限。
常見原因:
- 陣列開太大:
int arr[10000000][10000000];一開就要 TB 級別記憶體 - 無限遞迴或死迴圈建立變數:不斷分配新變數,不釋放舊的
- 動態分配洩漏:
new了卻沒delete,導致記憶體不斷累積
除錯方法:
- 計算陣列大小:一個
int是 4 bytes,10^6 個就是 4 MB- 題目如果限制 64 MB,最多能開 16 \times 10^6 個
int - 如果要開 2D 陣列,記憶體倍增,要很小心
- 題目如果限制 64 MB,最多能開 16 \times 10^6 個
- 改用動態分配:不是一次開整個陣列,而是邊讀邊存
- 優化資料結構:用更省記憶體的方式表示資料
MLE 優化技巧:
// 不要這樣(會爆炸)
int dp[100000][100000]; // 4GB 記憶體!
// 改成動態分配
vector<vector<int>> dp(n, vector<int>(m));
// 或者如果只需要前一行的資訊,用滾動陣列
int prev[100000], curr[100000];
// 或改用更省的資料結構(如 map 只存非零值)