Hướng dẫn bài BOATS

Trùm CUỐI 2025-12-15 1:45:13

Link đề bài

1. Phân tích đề bài

  • Chúng ta cần tìm một tổng trọng lượng s cố định sao cho số lượng cặp (w_i, w_j) thỏa mãn w_i + w_j = s là nhiều nhất.
  • N \le 50 và trọng lượng w_i \le N , nên tổng trọng lượng s của một cặp chỉ có thể nằm trong khoảng từ 2 (1+1) đến 100 (50+50).
  • Chiến lược: Thử tất cả các giá trị có thể của s và kiểm tra xem với mỗi s , ta ghép được bao nhiêu cặp.

2. Ý tưởng thuật toán

Sử dụng phương pháp Duyệt toàn bộ (Brute-force) kết hợp với Mảng đánh dấu (Frequency Array).

  1. Đếm tần suất: Đếm số lần xuất hiện của mỗi trọng lượng trong mảng đầu vào. Gọi mảng này là cnt.
  2. Duyệt các tổng s : Cho một vòng lặp chạy s từ 2 đến 2 \times N (tất cả các tổng có thể xảy ra).
  3. Tính số cặp với mỗi s :
    • Với mỗi s cố định, ta tính số cặp có thể tạo thành.
    • Duyệt các trọng lượng i từ 1 đến s/2 :
      • Nếu i \neq s - i : Số cặp tạo được là \min(\text{cnt}[i], \text{cnt}[s-i]) .
      • Nếu i = s - i (hai người cùng cân nặng): Số cặp tạo được là \lfloor \text{cnt}[i] / 2 \rfloor .
    • Cộng dồn số cặp lại để được kết quả cho giá trị s hiện tại.
  4. Cập nhật kết quả: So sánh số cặp của s hiện tại với kết quả lớn nhất (max_teams) đã tìm được trước đó và cập nhật.

3. Các bước thực hiện (Pseudo-code)

Đọc t (số bộ test)
Với mỗi bộ test:
    Đọc n
    Đọc mảng w, lưu tần suất xuất hiện vào mảng cnt (ví dụ: cnt[x] là số người nặng x)
    
    max_teams = 0
    
    Duyệt s từ 2 đến 2*n:
        current_teams = 0
        Duyệt i từ 1 đến (s - 1) / 2:
            j = s - i
            Nếu j <= n: // Đảm bảo trọng lượng j hợp lệ
                current_teams += min(cnt[i], cnt[j])
        
        // Xử lý trường hợp 2 người bằng nhau (nếu s chẵn)
        Nếu s là số chẵn:
            current_teams += cnt[s / 2] / 2
            
        max_teams = max(max_teams, current_teams)
        
    In ra max_teams

4. Lưu ý khi cài đặt

  • Giới hạn mảng: w_i \le 50 , mảng đếm cnt chỉ cần kích thước khoảng 55 hoặc 105 là đủ.
  • Phạm vi duyệt: Tổng s không nhất thiết phải duyệt đến 2N , chỉ cần duyệt từ tổng nhỏ nhất có thể (min + min thứ 2) đến tổng lớn nhất có thể (max + max thứ 2) trong mảng, nhưng với N nhỏ thì duyệt từ 2 đến 100 vẫn chạy rất nhanh.
  • Độ phức tạp: O(T \times N \times N) hoặc O(T \times N) , hoàn toàn thỏa mãn thời gian cho phép.