1. Bài toán, nhìn bằng hình
2. Vì sao brute force không làm nổi
3. Insight
4. BFS chạy trên chính input này
5. Đi lại từng bước
Pop 312/456/789 (depth 0). Sinh 12 neighbor. Một trong số đó là 132/456/789.
Pop 132/456/789 (depth 1). Neighbor thứ 2 của nó là 123/456/789 = target. Trả về dist = 2.
Visited set cứu chúng ta khỏi push trùng. Không có nó, queue phình theo 12^depth.
6. Code (click từng dòng để widget seek)
from collections import deque
target = (1,2,3,4,5,6,7,8,9)
EDGES = [(0,1),(1,2),(3,4),(4,5),(6,7),(7,8),
(0,3),(1,4),(2,5),(3,6),(4,7),(5,8)]
def solve(start):
q = deque([(start, 0)])
seen = {start}
while q:
s, d = q.popleft()
if s == target: return d
for i, j in EDGES:
t = list(s)
t[i], t[j] = t[j], t[i]
t = tuple(t)
if t not in seen:
seen.add(t)
q.append((t, d+1))
7. Biến thể & bẫy
- n×n tổng quát. n≤4 còn BFS được (16! ≈ 2·10¹³ — quá lớn, cần A* với Manhattan).
- Swap bất kỳ (không cần kề). Đáp án = n² − số chu trình của hoán vị. Công thức đóng, không cần BFS.
- Quên visited set. Queue phình mũ, TLE/MLE ngay cả với n=3.