Những Lưu Ý Quan Trọng Khi Lập Trình Thi Đấu
Tóm tắt
- Luôn kiểm tra kích thước mảng sau khi viết xong bài. Nên khai báo lớn hơn 2-4 lần so với giới hạn đề bài. Đặc biệt chú ý khi có nhiều biến như N, M, K...
- Phải đọc kỹ đề bài. Dữ liệu kiểm thử có thể có nhiều dạng khác nhau. Nếu đề không nói rõ không có cạnh song song hoặc tự vòng, hãy tự xử lý.
- Xác định rõ dữ liệu đầu vào và yêu cầu đầu ra. Ví dụ, khi đọc dữ liệu, hãy tự hỏi: x có phải là chỉ số, màu sắc, hay giá trị của đỉnh i không? Thông tin về cạnh (x, y, z) có thể không phải là cạnh x->y có trọng số z, mà có thể là y->z có trọng số x, hoặc thậm chí là y->x có trọng số z.
- Chú ý có phải là nhiều bộ test hay không, và tên file có chính xác không.
- Chú ý không bị tràn kiểu int. Trong các kỳ thi, có thể định nghĩa int là long long. Nếu tràn long long, hãy thử dùng unsigned long long hoặc chuyển sang long double rồi chuyển lại.
- Khi viết code, đầu óc phải tỉnh táo. Tránh các lỗi cơ bản như gõ nhầm N thành M, tmp1 thành tmp2, ls thành l, j thành i...
- Nếu cảm thấy mệt mỏi hoặc nôn nóng khi gỡ lỗi, hãy ra ngoài đi dạo rồi quay lại. Việc này giúp đầu óc sảng khoái hơn.
- Trong các buổi tập huấn, hãy chọn một nơi tốt (nếu có thể), nếu không sẽ gặp vấn đề như không nhìn rõ bảng, không tập trung được.
- Trong cuộc thi, tuyệt đối không được hoảng loạn.
- Khi suy nghĩ giải pháp, đừng vội tối ưu hóa hằng số. Ưu tiên tối ưu hóa độ phức tạp thuật toán.
- Đừng quên khởi tạo các biến! (Đặc biệt với nhiều bộ test)
- Nếu muốn sao lưu code, đừng sao chép trực tiếp file .cpp. Hãy sao chép code, sau đó tạo một file .cpp mới.
- Nếu không biết cách giải chính thức, hãy suy nghĩ về các phương pháp lấy điểm phần, và thử mở rộng chúng. Thường thì các bài toán hay sẽ có manh mối trong các điểm phần.
- Đối với các bài toán toán học "khó nhằn" (đặc biệt n <= 1e9), việc "đánh bảng" (brute force với các giá trị nhỏ) là rất quan trọng. Bảng kết quả có thể giúp ta tìm ra đáp án mà không cần đến các công thức phức tạp.
- Lưu đồ và quy hoạch động thường là các hướng giải khó nghĩ. Khi không có ý tưởng, hãy thử các hướng này.
- Khai báo mảng thật lớn! Luôn kiểm tra xem kích thước mảng đã đủ lớn chưa.
- Luôn đối chiếu kết quả với một giải pháp khác (đối chiếu). Dù không biết cách đối chiếu, hãy tự tạo nhiều bộ dữ liệu kiểm thử.
- Các bước kiểm tra trong 20 phút cuối kỳ thi: kiểm tra kích thước mảng, kiểm tra mẫu có chạy được không, kiểm tra các biến có bị nhầm lẫn không, đọc lại đề một lần nữa, và kiểm tra tên file.
- Hãy thử chạy code trên môi trường Linux. Nhiều lỗi biên dịch (CE) chỉ xuất hiện ở đây mà không có ở Windows.
- Tự tạo dữ liệu kiểm thử dựa trên đề bài. Đừng tự tin vào kết luận của mình.
- Đừng chỉ nghĩ đến các giải pháp lấy điểm phần. Hãy suy nghĩ về giải pháp chính thức. Đôi khi giải pháp chính thức còn dễ viết hơn.
- Trong cuộc thi, nếu biết cách giải chính thức, hãy viết ngay lập tức. Nếu không, hãy viết giải pháp bạo lực.
- Đừng dành quá nửa thời gian cuộc thi cho một bài toán (đặc biệt là T1).
- Các phép cắt tỉa có tác dụng tối ưu hóa nên được thêm vào, ngay cả khi chúng không hiệu quả trong trường hợp xấu nhất.
- Trong CodeForces, khi viết hàm băm (Hash), nên dùng băm kép và thêm yếu tố ngẫu nhiên hóa để tránh bị "hack".
- Tự tạo dữ liệu kiểm thử càng nhiều càng tốt. Việc này giúp phát hiện lỗi hiệu quả hơn là xem code.
- Sau khi giải xong các bài đơn giản, hãy suy nghĩ về các trường hợp biên.
- Khi có một ý tưởng nhỏ, hãy thử nó. Hãy thử tất cả các hướng tiếp cận có thể (DFS, BFS, Iterative Deepening...).
- Đối với các bài toán yêu cầu trả lời, hãy quan sát đặc điểm của dữ liệu trước khi viết code bạo lực.
- Đối chiếu không nên chỉ dùng `int n = 100, m = 100`. Hãy thử các giá trị n, m khác nhau, hoặc dùng `rand()`.
- Đối chiếu các bài toán về cây, hãy tạo các dữ liệu đặc biệt như "cây hoa cúc" (nhiều cạnh nối vào một đỉnh) và "cây dây" (độ sâu lớn).
- Trước khi chạy đối chiếu, hãy đảm bảo code đã được biên dịch.
- Hãy suy nghĩ về giải pháp trong khoảng 1.5 giờ đầu tiên của kỳ thi 4.5 giờ để ổn định và giảm bớt áp lực.
- Hãy có niềm tin! Đôi khi việc khai báo mảng lớn hoặc viết các giải pháp "lừa" có thể giúp bạn qua được bài.
- Khi code gặp lỗi lạ, hãy suy nghĩ kỹ nguyên nhân, đừng tự欺骗 mình.
- Đọc lại code một lần nữa sau khi đã chạy qua mẫu.
- Quan sát phạm vi dữ liệu. Nếu cảm thấy bài quá khó, hãy đọc lại đề để kiểm tra xem có bỏ sót điều kiện nào không.
Các Lỗi Thường Gặp Cụ Thể
Trên POJ (CE - Lỗi Biên Dịch)
- Thay thế thư viện万能头 bằng các thư viện cụ thể.
- Kiểm tra xem có truyền một long long vào hàm yêu cầu int không.
- Thay đổi ngôn ngữ trên POJ thành G++.
- Nếu DevC++ cũng báo lỗi `invalid types 'int[int]' for array subscript`, có thể bạn đã dùng một biến int như một mảng int[]. Hãy kiểm tra các tên biến trùng lặp.
Trên POJ (RE - Lỗi Chạy Thời Gian)
- Thay đổi ngôn ngữ trên POJ thành C++ và kiểm tra lại kiểu dữ liệu.
- Khai báo mảng lớn hơn 10 lần.
- Kiểm tra các trường hợp `sqrt(-xxx)`, `xxx/0`, `h[-5]`, `h[1047483647]`.
- Đối chiếu với code chuẩn hoặc nhúng code của bạn vào code chuẩn.
Trên OJ (MLE - Lỗi Dùng Quá Nhiều Bộ Nhớ)
- Điều chỉnh kích thước mảng (tăng hoặc giảm).
- Kiểm tra xem có rơi vào vòng lặp vô hạn không.
- Tối ưu hóa thuật toán.
Trên OJ hoặc thi (WA - Lỗi Sai Kết Quả)
- Dữ liệu nhỏ: tự chơi tay.
- Dữ liệu lớn: thử khai báo mảng lớn hơn.
- Định nghĩa int là long long.
- Trên UVA, lỗi định dạng (ví dụ: có dòng trống thừa) rất phổ biến.
Lỗi Chỉ Xuất Hiện Trên Linux
- `typedef long long uint;`
- `printf("%.3llf
", ans);`
- `define int long long` sau đó `typedef unsigned int uint;`
Lưu Ý Khác
- Nếu một biến thay đổi giá trị một cách lạ thường (đặc biệt với dữ liệu lớn), hãy thử khai báo mảng lớn hơn. Nếu lỗi biến mất, có nghĩa là mảng của bạn không đủ lớn.
- Khi viết cây phân đoạn động, trong hàm `pushdown`, hãy kiểm tra xem node có con trái/phải không để tránh mất dấu.
- Khi so sánh chuỗi, hãy dùng `strcmp(a, b)`.
- Các biến đếm như `cnt`, `cnt1`, `cnt2`... cần được phân biệt rõ ràng.
- Phân biệt toán tử dịch bit trái và phải.
- Xem kỹ yêu cầu đầu ra, đừng làm tròn hoặc lấy phần nguyên một cách mù quáng.
- Nếu không tìm ra lỗi, hãy thử viết lại code.
- Trong DFS, tránh duyệt thừa. Đặc biệt khi liệt kê các hoán vị, không chọn (5, 6) rồi lại chọn (6, 5).
- Luôn kiểm tra tràn int/long long. Nên dùng long long thay cho int.
- Khai báo mảng lớn hơn một chút để tránh các lỗi kỳ lạ.
- Phân biệt biến cục bộ và biến toàn cục.
- Trong DFS, hãy khôi phục trạng thái.
- Khi sửa lỗi, hãy sửa cho đủ.
- Chú ý định dạng đầu ra.
Về Quy Hoạch Động (DP)
- Chú ý thứ tự cập nhật trạng thái. Đôi khi cần cập nhật ngược lại.
- Đã bao phủ tất cả trạng thái chưa? (Đúng đắn)
- Khi tính trạng thái sau, trạng thái trước đã được xác định chưa? (Vô hậu)
- Đã sửa đổi trạng thái đã được xác định chưa?
Về Cây Phân Cành (Tree Chain Decomposition)
- Để tìm LCA, hãy dùng:
if (depth[top[x]] < depth[top[y]]) swap(x, y);
Thay vì:
if (depth[x] < depth[y]) swap(x, y);
- Trong hàm `get_lca`, hãy dùng `while(top[x] != top[y])` thay vì `if(top[x] != top[y])`.
Về Nhập Liệu
Về Các Hàm Thư Viện
Các Lỗi Nhỏ
- Xóa hết các câu lệnh gỡ lỗi (`debug`).
- Chú ý định dạng đầu ra.
- Gọi hàm khởi tạo `init` nếu có.
- Xóa sạch dữ liệu cho các bộ test tiếp theo.
- Trong các bài toán lấy模, nếu kết quả âm, hãy cộng P trước khi in ra.
- Khởi tạo `jie[0] = jieni[0] = 1`.
- Trong tìm kiếm có nhớ, hãy kiểm tra `if (mp.count(...))` và `return mp[] = res;`.
- Trong các phép toán lấy模, chú ý kết quả âm.
- Phân biệt chỉ số và giá trị, đặc biệt trong các mảng hoán vị và mảng vị trí.
- Vector rỗng cũng chiếm không gian bộ nhớ. Hạn chế khai báo quá nhiều vector.
- `vector.clear()` không giải phóng bộ nhớ ngay. Để giải phóng, hãy dùng `vector().swap(vec)`.
Thẻ:
lập trình thi đấu
thuật toán
Gỡ lỗi
Cấu trúc dữ liệu
C++
Đăng vào ngày 26 tháng 5 lúc 16:28