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)\).
Ví dụ minh họa: Lưới có vật cản (từng bước)¶
Xét lưới \(3 \times 3\) (tức \(n=3, m=3\)), cần đi từ \((0,0)\) đến \((3,3)\). Có 2 ô cấm: \((1,1)\) và \((2,1)\).
Mở rộng: Trace chi tiết
Bước 1: Sắp xếp ô cấm → [(1,1), (2,1)]
Bước 2: Tính dp cho từng ô cấm
dp[0] = C(1+1, 1) = C(2,1) = 2(2 đường từ \((0,0)\) đến \((1,1)\))dp[1] = C(2+1, 2) = C(3,2) = 3(3 đường từ \((0,0)\) đến \((2,1)\))- Trừ đường qua \((1,1)\):
dp[0] × C((2-1)+(1-1), (2-1)) = 2 × C(1,1) = 2 × 1 = 2 dp[1] = (3 - 2) % MOD = 1
Bước 3: Đường đến đích (3,3)
- Tổng:
C(3+3, 3) = C(6,3) = 20 - Trừ qua \((1,1)\):
dp[0] × C((3-1)+(3-1), (3-1)) = 2 × C(4,2) = 2 × 6 = 12 - Trừ qua \((2,1)\):
dp[1] × C((3-2)+(3-1), (3-2)) = 1 × C(3,1) = 1 × 3 = 3 - Kết quả:
(20 - 12 - 3) % MOD = 5đường hợp lệ.
7. Mẹo và lưu ý¶
7.1 Các trường hợp đặc biệt¶
| Trường hợp | Kết quả | Giải thích |
|---|---|---|
| \(n=0\) hoặc \(m=0\) (lưới 1D) | \(1\) | Chỉ có đúng một đường đi thẳng |
| \(n=m=0\) | \(1\) | Điểm xuất phát trùng điểm đích |
| Ô cấm nằm tại \((0,0)\) | \(0\) | Không thể xuất phát |
| Ô cấm nằm tại \((n,m)\) | \(0\) | Không thể đến đích |
| \(k > n+m\) (nhiều ô cấm) | \(O(k^2)\) | Độ phức tạp phụ thuộc số ô cấm, không phụ thuộc kích thước lưới |
7.2 Cạm bẫy thường gặp¶
- Modulo âm: Khi thực hiện phép trừ modulo, luôn dùng
(x - y + MOD) % MODđể tránh kết quả âm. - Sort sai thứ tự: Phải sắp xếp ô cấm theo thứ tự topo (từ trên xuống, trái qua phải). Nếu ô \(j\) không nằm ở góc trên-trái của ô \(i\), không thể đi từ \(j\) đến \(i\).
- Bỏ quên trường hợp ô cấm nằm ngoài vùng: Một số ô cấm có thể có tọa độ lớn hơn đích, cần lọc
banned[i].first <= n && banned[i].second <= m. - Nhầm \(\binom{n+m}{n}\) với \(\binom{2n}{n}\): Chỉ khi \(n=m\) thì mới bằng \(\binom{2n}{n}\). Với lưới chữ nhật, dùng \(\binom{n+m}{n}\).
- Quên tính chất đối xứng: \(\binom{n+m}{n} = \binom{n+m}{m}\), chọn cái nào nhỏ hơn để tính nhanh hơn.
7.3 Mở rộng: Các đồng nhất thức tổ hợp liên quan¶
| Đồng nhất thức | Công thức | Ý nghĩa trên lưới |
|---|---|---|
| Vandermonde | \(\sum_{i=0}^{k}\binom{n}{i}\binom{m}{k-i} = \binom{n+m}{k}\) | Chọn \(k\) bước phải từ mặt phẳng con |
| Hockey-stick | \(\sum_{i=0}^{n}\binom{i+k}{k} = \binom{n+k+1}{k+1}\) | Tổng đường đi đến các điểm trên cùng hàng/cột |
| Catalan | \(C_n = \frac{1}{n+1}\binom{2n}{n}\) | Đường đi không vượt đường chéo |
8. Bài tập luyện tập¶
| Mã bài | Tên bài tập | Độ khó | Kiểu bài tập (Bản chất) | Bài học lý thuyết |
|---|---|---|---|---|
gp-basic |
Đường đi trên lưới cơ bản | ⭐⭐ | \(C(n+m-2, n-1)\) | Đếm Đường Đi Trên Lưới |
gp-dice |
Dice combinations | ⭐ | DP tổng xúc xắc | Đếm Đường Đi Trên Lưới |
gp-dyck |
Dyck path | ⭐⭐ | Số Catalan | Đếm Đường Đi Trên Lưới |
gp-robot |
Robot trên lưới | ⭐⭐ | DP 2D vật cản | Đếm Đường Đi Trên Lưới |
gp-maze |
Mê cung tổng lớn nhất | ⭐⭐ | DP đường đi max sum | Đếm Đường Đi Trên Lưới |
gp-multiset |
Tổ hợp có lặp | ⭐⭐ | \(C(S+n-1,n-1)\) | Đếm Đường Đi Trên Lưới |
gp-binom-sum |
Tổng nhị thức Vandermonde | ⭐⭐ | \(\sum C(n,i)C(m,i)\) | Đếm Đường Đi Trên Lưới |
gp-paths-all |
Đường đi không chạm chéo | ⭐⭐⭐ | Catalan không chạm | Đếm Đường Đi Trên Lưới |
gp-obstacle |
Lưới có vật cản | ⭐⭐⭐⭐ | IE + DP đường đi | Đếm Đường Đi Trên Lưới |
gp-ksteps |
Đường đi K bước trên đồ thị | ⭐⭐⭐⭐ | Lũy thừa ma trận | Đếm Đường Đi Trên Lưới |