| def count_match_pairings(n): |
| """ |
| Đệ quy: Đếm số cách ghép cặp n đội thành các trận đấu. |
| |
| Với n đội (n chẵn), số cách ghép cặp thành n/2 trận đấu là: |
| f(0) = 1 (không có đội nào → 1 cách: không làm gì) |
| f(2) = 1 (2 đội → 1 trận) |
| f(n) = (n - 1) * f(n - 2) |
| |
| Giải thích: Đội thứ nhất có (n-1) lựa chọn đối thủ, |
| sau khi ghép xong thì còn (n-2) đội → gọi đệ quy f(n-2). |
| |
| Args: |
| n: Số đội (phải là số chẵn không âm). |
| |
| Returns: |
| Số cách ghép cặp các đội thành trận đấu. |
| |
| Raises: |
| ValueError: Nếu n là số lẻ hoặc âm. |
| """ |
| if n < 0 or n % 2 != 0: |
| raise ValueError("Số đội phải là số chẵn không âm") |
|
|
| |
| if n == 0 or n == 2: |
| return 1 |
|
|
| |
| |
| return (n - 1) * count_match_pairings(n - 2) |
|
|
|
|
| def display_match_bracket_recursive(teams, match_list=None, depth=0): |
| """ |
| Đệ quy: Hiển thị một ví dụ cách ghép cặp trận đấu. |
| |
| Hàm đệ quy lấy 2 đội đầu tiên ghép thành 1 trận, |
| rồi gọi đệ quy với các đội còn lại. |
| |
| Args: |
| teams: Danh sách các đội còn lại cần ghép. |
| match_list: Danh sách tích lũy các trận đã ghép. |
| depth: Độ sâu đệ quy (dùng để đánh số trận). |
| """ |
| if match_list is None: |
| match_list = [] |
|
|
| |
| if len(teams) < 2: |
| return match_list |
|
|
| |
| match_num = depth + 1 |
| match_list.append((match_num, teams[0], teams[1])) |
| return display_match_bracket_recursive(teams[2:], match_list, depth + 1) |
|
|
|
|
| def print_bracket(n): |
| """ |
| In kết quả ghép cặp cho n đội bằng đệ quy. |
| |
| Args: |
| n: Số đội (phải là số chẵn không âm). |
| """ |
| if n < 2: |
| print("Cần ít nhất 2 đội để tạo trận đấu.") |
| return |
|
|
| teams = list(range(1, n + 1)) |
| matches = display_match_bracket_recursive(teams) |
|
|
| print(f"\n--- Ví dụ ghép cặp cho {n} đội (Đệ quy) ---") |
| for match_num, team_a, team_b in matches: |
| print(f" Trận {match_num}: Đội {team_a} vs Đội {team_b}") |
|
|
|
|
| if __name__ == "__main__": |
| |
| print("=" * 50) |
| print(" BÀI TOÁN GHÉP CẶP TRẬN ĐẤU (ĐỆ QUY)") |
| print("=" * 50) |
|
|
| for num_teams in range(2, 12, 2): |
| ways = count_match_pairings(num_teams) |
| print(f" {num_teams} đội → {ways} cách ghép cặp") |
|
|
| print("-" * 50) |
|
|
| |
| n = 6 |
| total = count_match_pairings(n) |
| print(f"\nVới {n} đội, tổng có {total} cách ghép cặp trận đấu.") |
| print_bracket(n) |
|
|
| |
| n = 8 |
| total = count_match_pairings(n) |
| print(f"\nVới {n} đội, tổng có {total} cách ghép cặp trận đấu.") |
| print_bracket(n) |
|
|