Bài 59: Đếm Đường Đi Trên Lưới¶
Tác giả: FPTOJ Team
Nội dung tham khảo từ: CP-Algorithms, VNOI Wiki
1. Bài Toán Cơ Bản¶
1.1 Đếm đường đi từ (0,0) đến (n,m)¶
Mỗi bước chỉ được đi phải hoặc xuống. Từ \((0,0)\) đến \((n,m)\) cần đúng \(n\) bước xuống và \(m\) bước phải, tổng \(n + m\) bước.
Số cách chọn vị trí \(n\) bước xuống trong \(n + m\) bước:
Ví dụ: Từ \((0,0)\) đến \((2,3)\): \(\binom{5}{2} = 10\) đường đi.
2. Đếm đường đi có vật cản¶
2.1 Bài toán¶
Trên lưới có \(k\) ô bị cấm. Đếm số đường đi từ \((0,0)\) đến \((n,m)\) không đi qua ô cấm nào.
2.2 Ý tưởng¶
Sắp xếp các ô cấm theo thứ tự (từ trái qua phải, trên xuống dưới). Với mỗi ô cấm \(i\), đếm số đường đi từ gốc đến \(i\) mà không qua ô cấm nào khác, rồi trừ đi đóng góp vào đích.
Gọi \(f(i)\) = số đường đi từ \((0,0)\) đến ô cấm \(i\) mà không qua ô cấm nào khác.
Kết quả = \(\text{Paths}(0 \to \text{đích}) - \sum_i f(i) \times \text{Paths}(i \to \text{đích})\)
3. Catalan Numbers & Đường đi không vượt đường chéo¶
3.1 Bài toán Dyck Path¶
Đếm đường đi từ \((0,0)\) đến \((n,n)\) chỉ đi phải hoặc xuống, không bao giờ đi trên đường chéo chính (tức tại mọi thời điểm số bước phải ≤ số bước xuống).
3.2 Các bài toán tương đương¶
Catalan number xuất hiện ở rất nhiều bài toán:
- Đếm dãy ngoặc đúng độ dài \(2n\)
- Đếm cây nhị phân có \(n\) đỉnh
- Đếm cách chia đa giác lồi \(n+2\) cạnh thành tam giác
- Đếm đường đi Dyck
4. Tổng đường đi trên lưới¶
4.1 Bài toán¶
Tính tổng số đường đi từ \((0,0)\) đến mọi ô \((i, j)\) trên lưới \(n \times m\).
4.2 Quy hoạch động¶
với \(\text{dp}[0][0] = 1\).
Tổng = \(\sum_{i=0}^{n} \sum_{j=0}^{m} \text{dp}[i][j]\)
5. Grid với nhiều loại bước¶
5.1 Bài toán¶
Từ \((0,0)\) đến \((n,m)\), mỗi bước có thể đi \((+1, 0), (0, +1), (+1, +1)\). Đếm số đường đi.
5.2 Quy hoạch động¶
Hoặc dùng ma trận chuyển nếu \(n\) rất lớn (xem Bài 57).
6. Đếm đường đi trên lưới 3D¶
6.1 Bài toán¶
Từ \((0,0,0)\) đến \((a,b,c)\), mỗi bước đi \((+1,0,0), (0,+1,0), (0,0,+1)\).
7. Bài tập luyện tập¶
Bài 1: Đếm đường đi cơ bản¶
Đề bài: Cho lưới \(n \times m\). Mỗi bước chỉ được đi sang phải hoặc xuống. Từ góc trái trên \((1,1)\) đến góc phải dưới \((n,m)\), có bao nhiêu đường đi?
Input: 2 số nguyên \(n, m\) \((1 \leq n, m \leq 10^6)\)
Output: Số đường đi modulo \(10^9 + 7\).
Ví dụ:
| Input | Output |
|---|---|
2 3 |
3 |
3 3 |
6 |
Lời giải
Đáp án = \(C(n+m-2, n-1)\). Precompute factorial và modular inverse.
Bài 2: Grid Paths (7x7)¶
Đề bài: Cho lưới \(7 \times 7\). Có một số ô bị chặn. Đếm số đường đi từ góc trái trên đến góc phải dưới, chỉ đi phải hoặc xuống, không qua ô chặn.
Input: 48 ký tự. Mỗi ký tự là . (trống) hoặc # (chặn), đọc từ trái sang phải, trên xuống dưới. Ô \((1,1)\) và \((7,7)\) luôn trống.
Output: Số đường đi.
Ví dụ: (input toàn .) → Output: 12870
Lời giải
Dùng bitmask DP hoặc BFS đếm đường đi trên lưới nhỏ.
Bài 3: Dyck Path (Catalan)¶
Đề bài: Cho số nguyên \(n\). Đếm số đường đi từ \((0,0)\) đến \((n,n)\) chỉ đi phải hoặc xuống, không bao giờ đi trên đường chéo (tức tại mọi thời điểm số bước phải ≤ số bước xuống).
Input: Số nguyên \(n\) \((1 \leq n \leq 10^6)\)
Output: Kết quả modulo \(10^9 + 7\).
Ví dụ:
| Input | Output |
|---|---|
3 |
5 |
4 |
14 |
Giải thích (test 1): Catalan(3) = 5. Các đường đi hợp lệ từ (0,0) đến (3,3).
Lời giải
\(C_n = \frac{1}{n+1}\binom{2n}{n}\).
Bài 4: Dice Combinations¶
Đề bài: Có bao nhiêu cách để tung xúc xắc (1-6) sao cho tổng các mặt bằng \(n\)?
Input: Số nguyên \(n\) \((1 \leq n \leq 10^6)\)
Output: Kết quả modulo \(10^9 + 7\).
Ví dụ:
| Input | Output |
|---|---|
3 |
4 |
4 |
8 |
Giải thích (test 1): Tổng = 3: {1+1+1, 1+2, 2+1, 3} = 4 cách.
Lời giải
\(dp[i] = dp[i-1] + dp[i-2] + \cdots + dp[i-6]\), dùng prefix sum để tối ưu.