Giai đoạn 3 – Thuật toán

Mục tiêu giai đoạn: HS nắm các kỹ thuật thường gặp ở bài 3–4 của đề: vét cạn, đệ quy/quay lui, tham lam, hai con trỏ, tìm kiếm nhị phân, quy hoạch động cơ bản, loang trên lưới.

Quan trọng hơn cả: biết lấy điểm từng phần – luôn có lời giải "trâu" trước khi tối ưu.


Bảng tiến độ

BuổiChủ đềNội dung chínhBài tập gợi ý
29Duyệt / vét cạnThử mọi khả năng; giảm số vòng lặp bằng toánTìm x, y, z nguyên dương với x + y + z = n và điều kiện; đếm bộ ba Pytago ≤ n
30Đệ quyHàm gọi chính nó, điều kiện dừng; sys.setrecursionlimitGiai thừa, Fibonacci, tổng chữ số đệ quy, tháp Hà Nội
31Quay luiSinh dãy nhị phân, hoán vị, tổ hợp; itertools.product / permutations / combinationsLiệt kê xâu nhị phân độ dài n, hoán vị 1..n, chọn k trong n
32Luyện tập vét cạnDuyệt tập con (n ≤ 20)Tập con có tổng bằng S; chia kẹo thành 2 phần chênh lệch ít nhất
33Tham lamChọn phương án tốt nhất ở mỗi bước; tìm phản ví dụĐổi tiền ít tờ nhất; chọn nhiều hoạt động không giao nhau nhất (sort theo giờ kết thúc); xếp hàng chờ ít nhất
34Luyện tập tham lamSort + tham lamGhép cặp chênh lệch nhỏ nhất, chở hàng với xe tải trọng W, số lớn nhất ghép từ các số
35Hai con trỏHai chỉ số cùng chạy trên dãyDãy đã sort – cặp tổng bằng k; đoạn dài nhất có tổng ≤ S (số dương); trộn hai dãy tăng
36Tìm kiếm nhị phânTự viết; bisect_left, bisect_rightKiểm tra x có trong dãy (q truy vấn); đếm số phần tử trong [l, r]
37Chặt nhị phân đáp ánĐáp án "đơn điệu" → tìm nhị phân trên đáp ánCắt gỗ (chiều cao cưa lớn nhất); in sách vào k ngày (mỗi ngày đọc ít nhất bao nhiêu trang)
38Quy hoạch động nhập mônGhi nhớ kết quả bài toán con; công thức truy hồiLeo cầu thang 1–2 bậc; số đường đi trên lưới; Fibonacci n ≤ 10⁵ (mod 10⁹+7)
39QHĐ cơ bảnBảng phương án 1 chiều / 2 chiềuDãy con tăng dài nhất O(n²); đổi tiền ít xu nhất; cái túi 0/1 (n ≤ 100, W ≤ 10⁴)
40Luyện tập QHĐNhận dạng bài QHĐTổng lớn nhất không chọn 2 số kề nhau; ★★★ xâu con chung dài nhất
41Loang (BFS) trên lướiHàng đợi deque, 4 hướng điĐếm số hòn đảo; đường đi ngắn nhất trong mê cung
42Luyện tập loangLoang nhiều nguồn, DFS bằng ngăn xếpDiện tích vùng lớn nhất; lửa cháy lan; ★★★ đồ thị đơn giản (danh sách kề)
43Ôn tập tổng hợpNhận dạng bài: đọc đề → đoán kỹ thuật6–8 bài trộn lẫn các dạng, chỉ cần nói hướng giải, code 2–3 bài
44Thi thử lần 33–4 bài, 150 phút, đúng thể lệLấy đề Tin học trẻ năm trước

Code mẫu cốt lõi

Quay lui – sinh mọi xâu nhị phân độ dài n

n = int(input())
x = [0] * n

def thu(i):
    if i == n:
        print("".join(map(str, x)))
        return
    for v in (0, 1):
        x[i] = v
        thu(i + 1)

thu(0)

Khi thi được dùng thư viện cho nhanh:

from itertools import product, permutations, combinations
for t in product([0, 1], repeat=n): ...
for p in permutations(range(1, n + 1)): ...
for c in combinations(a, k): ...

Tham lam – chọn nhiều hoạt động nhất

hd = sorted(hd, key=lambda x: x[1])   # sắp theo giờ kết thúc
dem, ket_thuc = 0, -1
for bd, kt in hd:
    if bd >= ket_thuc:
        dem += 1
        ket_thuc = kt

Hai con trỏ – đoạn dài nhất có tổng ≤ S (các số dương)

best = tong = l = 0
for r in range(n):
    tong += a[r]
    while tong > S:
        tong -= a[l]
        l += 1
    best = max(best, r - l + 1)

Tìm kiếm nhị phân

from bisect import bisect_left, bisect_right
a.sort()
dem = bisect_right(a, r) - bisect_left(a, l)   # số phần tử trong [l, r]

# Chặt nhị phân đáp án: tìm x nhỏ nhất mà dat(x) đúng
lo, hi = 0, 10**18
while lo < hi:
    mid = (lo + hi) // 2
    if dat(mid):
        hi = mid
    else:
        lo = mid + 1

Gợi nhớ trò chơi đoán số (Buổi 6): mỗi lần đoán loại được một nửa → chỉ cần ~log₂n lần.

QHĐ – leo cầu thang

# f[i] = số cách lên bậc i, mỗi bước 1 hoặc 2 bậc
f = [0] * (n + 1)
f[0] = 1
for i in range(1, n + 1):
    f[i] = f[i - 1] + (f[i - 2] if i >= 2 else 0)

Cách dạy QHĐ: luôn hỏi 3 câu – (1) f[i] nghĩa là gì? (2) f[i] tính từ đâu? (3) giá trị đầu tiên là gì?

Loang BFS – đếm số hòn đảo

from collections import deque
m, n = map(int, input().split())
g = [input().strip() for _ in range(m)]        # '#': đất, '.': nước
da_tham = [[False] * n for _ in range(m)]
dem = 0
for i in range(m):
    for j in range(n):
        if g[i][j] == '#' and not da_tham[i][j]:
            dem += 1
            q = deque([(i, j)])
            da_tham[i][j] = True
            while q:
                x, y = q.popleft()
                for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)):
                    u, v = x + dx, y + dy
                    if 0 <= u < m and 0 <= v < n and g[u][v] == '#' and not da_tham[u][v]:
                        da_tham[u][v] = True
                        q.append((u, v))
print(dem)

Liên hệ Scratch: giống công cụ "đổ màu" (tô loang) trong trình vẽ.


Phân hóa cho 2 học sinh

  • Lớp 7: ưu tiên vét cạn, tham lam, tìm kiếm nhị phân trên mảng, QHĐ 1 chiều (buổi 29, 31, 33, 35, 36, 38). Đây là những phần mang lại nhiều điểm nhất.
  • Lớp 8: đi hết bảng, thêm chặt nhị phân đáp án, QHĐ 2 chiều, loang BFS.
  • Không cần dạy: cây phân đoạn, đồ thị nâng cao (Dijkstra…), hình học – hiếm gặp ở bảng THCS và tốn nhiều thời gian. Nếu em lớp 8 tiến bộ nhanh và đi tiếp vòng toàn quốc, bổ sung sau.
Zalo