bồi dưỡng học sinh giỏi môn tin học thpt chuyên đề các PHƯƠNG PHÁP tìm KIẾM TRÊN đồ THỊ

21 461 1
bồi dưỡng học sinh giỏi môn tin học thpt chuyên đề các PHƯƠNG PHÁP tìm KIẾM TRÊN đồ THỊ

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

CÁC PHƯƠNG PHÁP TÌM KIẾM TRÊN ĐỒ THỊ Một toán quan trọng lí thuyết đồ thị toán duyệt tất đỉnh đến từ đỉnh xuất phát Vấn đề đưa toán liệt kê mà yêu cầu không bỏ sót hay lặp lại đỉnh Chính mà ta phải xây dựng thuật toán cho phép duyệt cách hệ thống đỉnh, thuật toán gọi thuật toán tìm kiếm đồ thị (graph traversal) Ta quan tâm đến hai thuật toán nhất: thuật toán tìm kiếm theo chiều sâu thuật toán tìm kiếm theo chiều rộng Thuật toán tìm kiếm theo chiều sâu : a Thuật toán tìm kiếm theo chiều sâu: Ý tưởng: Tư tưởng thuật toán tìm kiếm theo chiều sâu (Depth-First Search - DFS) trình bày sau: Trước hết, dĩ nhiên đỉnh s đến từ s, tiếp theo, với cung (s, x) đồ thị x đến từ s Với đỉnh x tất nhiên đỉnh y nối từ x đến từ s Điều gợi ý cho ta viết thủ tục đệ quy DFSVisit(u) mô tả việc duyệt từ đỉnh u cách thăm đỉnh u tiếp tục trình duyệt DFSVisit(v) với v đỉnh chưa thăm nối từ u Kĩ thuật đánh dấu sử dụng để tránh việc liệt kê lặp đỉnh: Khởi tạo avail[v]:=true, ∀v∈V, lần thăm đỉnh, ta đánh dấu đỉnh lại (avail[v]:=false) để bước duyệt đệ quy không duyệt lại đỉnh Thuật toán: procedure DFSVisit(u ∈ V); //Thuật toán tìm kiếm theo chiều sâu từ đỉnh u begin avail[u] := False; //avail[u] = False ⇔ u thăm Output ← u; //Liệt kê u for ∀v ∈ V:(u, v)∈ E //Duyệt đỉnh v chưa thăm nối từ u if avail[v] then DFSVisit(v); end; begin //Chương trình Input → Đồ thị G for ∀v ∈ V avail[v] := True; //Đánh dấu đỉnh chưa thăm DFSVisit(s); end b Thuật toán tìm đường theo DFS: Bài toán tìm đường đi: Cho đồ thị G=(V,E) hai đỉnh s, t ∈ V Nhắc lại định nghĩa đường đi: Một dãy đỉnh: P= (∀i: (pi-1, pi) ∈ E) gọi đường từ s tới t, đường gồm k+1 đỉnh p0 , p1, …, pk cạnh (p0, p1), (p1, p2), …,(pk-1, pk) Đỉnh s gọi đỉnh đầu đỉnh t gọi đỉnh cuối đường Nếu tồn đường từ s tới t, ta nói s đến t t đến từ s: s t Thuật toán: Để lưu lại đường từ đỉnh xuất phát s, thủ tục DFSVisit(u), trước gọi đệ quy DFSVisit(v) với v đỉnh chưa thăm nối từ u chưa đánh dấu), ta lưu lại vết đường từ u tới v cách đặt trace[v]:=u, tức trace[v] lưu lại đỉnh liền trước v đường từ s tới v Khi thuật toán DFS kết thúc, đường từ s tới t là: procedure DFSVisit(u∈V); //Thuật toán tìm kiếm theo chiều sâu từ đỉnh u begin avail[u] := False; //avail[u] = False ⇔ u thăm for ∀ v∈ V:(u, v)∈ E //Duyệt đỉnh v chưa thăm nối từ u if avail[v] then begin trace[v] := u; //Lưu vết đường đi, đỉnh liền trước v đường từ s tới v u DFSVisit(v); //Gọi đệ quy để tìm kiếm theo chiều sâu từ đỉnh v end; end; begin / /Chương trình Input → Đồ thị G, đỉnh xuất phát s, đỉnh đích t; for ∀v ∈ V avail[v] := True; //Đánh dấu đỉnh chưa thăm DFSVisit(s); if avail[t] then //s đến t «Truy theo vết từ t để tìm đường từ s tới t»; end Có thể không cần mảng đánh dấu avail[1 … n] mà dùng mảng trace[1 … n] để đánh dấu: Khởi tạo phần tử mảng trace[1 … n] là: Trace[s]≠0 Trace[v]=0, ∀v≠s Khi điều kiện để đỉnh v chưa thăm trace[v] = 0, từ đỉnh u thăm đỉnh v, phép gán trace[v]= u kiêm công việc đánh dấu v thăm (trace[v] ≠ 0) Tính chất BFS Nếu ta xếp danh sách kề đỉnh theo thứ tự tăng dần thuật toán DFS trả đường có thứ tự từ điển nhỏ số tất đường từ s tới tới t c Thuật toán duyệt đồ thị theo DFS Cài đặt ứng dụng thuật toán DFS để liệt kê đỉnh đến từ đỉnh Thuật toán DFS dùng để duyệt qua đỉnh cạnh đồ thị viết sau: procedure DFSVisit(u∈V); //Thuật toán tìm kiếm theo chiều sâu từ đỉnh u begin Time := Time + 1; d[u] := Time; //Thời điểm duyệt đến u Output ← u; //Liệt kê u for ∀v∈V:(u, v) ∈E //Duyệt đỉnh v nối từ u if d[v] = then DFSVisit(v); //Nếu v chưa thăm, gọi đệ quy để tìm // kiếm theo chiều sâu từ đỉnh v Time := Time + 1; f[u] := Time; //Thời điểm duyệt xong u end; begin //Chương trình Input → Đồ thị G for ∀v∈V d[v] := 0; //Mọi đỉnh chưa duyệt đến Time := 0; for ∀v∈V if d[v] = then DFSVisit(v); end Thời gian thực giải thuật DFS đánh giá số lần gọi thủ tục DFSVisit (|V| lần) cộng với số lần thực vòng lặp for bên thủ tục DFSVisit Chính vậy: • Nếu đồ thị biểu diễn danh sách kề danh sách liên thuộc, vòng lặp for bên thủ tục DFSVisit (xét tổng thể chương trình) duyệt qua tất cạnh đồ thị (mỗi cạnh hai lần đồ thị vô hướng, cạnh lần đồ thị có hướng) Trong trường hợp này, thời gian thực giải thuật DFS Θ(|V| + |E|) • Nếu đồ thị biểu diễn ma trận kề, vòng lặp for bên thủ tục DFSVisit phải duyệt qua tất đỉnh … n Trong trường hợp thời gian thực giải thuật DFS Θ(|V| + |V|2) = Θ(| V|2) • Nếu đồ thị biểu diễn danh sách cạnh, vòng lặp for bên thủ tục DFSVisit phải duyệt qua tất danh sách cạnh lần thực thủ tục Trong trường hợp thời gian thực giải thuật DFS Θ(|V||E|) Thuật toán tìm kiếm theo chiều rộng: a Thuật toán tìm kiếm theo chiều rộng Ý tưởng: s u u s v v s s … Thăm trước tất đỉnh v s … Thăm sau tất đỉnh u Tư tưởng thuật toán tìm kiếm theo chiều rộng (Breadth-First Search – BFS) “lập lịch” duyệt đỉnh Việc thăm đỉnh lên lịch duyệt đỉnh nối từ cho thứ tự duyệt ưu tiên chiều rộng (đỉnh gần đỉnh xuất phát s duyệt trước) Đầu tiên ta thăm đỉnh s Việc thăm đỉnh s phát sinh thứ tự thăm đỉnh u1, u2, … nối từ s (những đỉnh gần s nhất) Tiếp theo ta thăm đỉnh u1, thăm đỉnh u1 lại phát sinh yêu cầu thăm đỉnh r1, r2, … nối từ u1 Nhưng rõ ràng đỉnh r “xa” s đỉnh u nên chúng thăm tất đỉnh u thăm Tức thứ tự duyệt đỉnh là: s, u1, u2, … , r1, r2, … Thuật toán tìm kiếm theo chiều rộng sử dụng danh sách để chứa đỉnh “chờ” thăm Tại bước, ta thăm đỉnh đầu danh sách, loại khỏi danh sách cho đỉnh chưa “xếp hàng” kề với xếp hàng thêm vào cuối danh sách Thuật toán kết thúc danh sách rỗng Vì nguyên tắc vào trước trước, danh sách chứa đỉnh chờ thăm tổ chức dạng hàng đợi (Queue): Nếu ta có Queue hàng đợi với thủ tục Push(r) để đẩy đỉnh r vào hàng đợi hàm Pop trả đỉnh lấy từ hàng đợi thuật toán BFS viết sau: Thuật toán: Queue := (s); //Khởi tạo hàng đợi gồm đỉnh s for ∀v∈V avail[v] := True; avail[s] := False; //Đánh dấu có đỉnh s xếp hàng repeat //Lặp tới hàng đợi rỗng u := Pop; //Lấy từ hàng đợi đỉnh u Output ← u; //Liệt kê u for ∀v∈V:avail[v] and (u, v) ∈ E //Xét đỉnh v kề u chưa //đẩy vào hàng đợi begin Push(v); //Đẩy v vào hàng đợi avail[v] := False; //Đánh dấu v xếp hàng end; until Queue = Ø; Thuật toán tìm đường theo BFS: Queue := (s); //Khởi tạo hàng đợi gồm đỉnh s for ∀v∈V avail[v] := True; avail[s] := False; //Đánh dấu có đỉnh s xếp hàng repeat //Lặp tới hàng đợi rỗng u := Pop; //Lấy từ hàng đợi đỉnh u for ∀v∈V:avail[v] and (u, v) ∈ E //Xét đỉnh v kề u chưa //đẩy vào hàng đợi begin trace[v] := u; //Lưu vết đường Push(v); //Đẩy v vào hàng đợi avail[v] := False; //Đánh dấu v xếp hàng end; until Queue = Ø; if avail[t] then //s tới t «Truy theo vết từ t để tìm đường từ s tới t»; Tương tự thuật toán tìm kiếm theo chiều sâu, ta dùng mảng Trace[1 … n] kiêm chức đánh dấu Tính chất BFS Thuật toán BFS trả đường qua cạnh số tất đường từ s tới t Nếu ta xếp danh sách kề đỉnh theo thứ tự tăng dần có nhiều đường từ s tới t qua cạnh thuật toán BFS trả đường có thứ tự từ điển nhỏ số đường c Thuật toán duyệt đồ thị theo BFS Tương tự thuật toán DFS, thực tế, thuật toán BFS dùng để xác định thứ tự đỉnh đồ thị viết theo mô hình sau: procedure BFSVisit(s∈V); begin Queue := (s); //Khởi tạo hàng đợi gồm đỉnh s Time := Time + 1; d[s] := Time; //Duyệt đến đỉnh s repeat //Lặp tới hàng đợi rỗng u := Pop; //Lấy từ hàng đợi đỉnh u Time := Time+1; F[u]:=Time; //Ghi nhận thời điểm duyệt xong đỉnh u Output ← u; //Liệt kê u for ∀v∈V:(u, v) ∈E //Xét đỉnh v kề u if d[v] = then //Nếu v chưa duyệt đến begin Push(v); //Đẩy v vào hàng đợi Time := Time + 1; d[v] := Time; //Ghi nhận thời điểm duyệt đến đỉnh v end; until Queue = Ø; end; begin //Chương trình Input → Đồ thị G; for ∀v∈V d[v] := 0; //Mọi đỉnh chưa duyệt đến Time := 0; for ∀v∈V if d[v]=0 then BFSVisit(v); end Thời gian thực giải thuật BFS tương tự DFS, Θ(|V| + |E|) đồ thị biểu diễn danh sách kề danh sách liên thuộc, Θ(|V|2) đồ thị biểu diễn ma trận kề, Θ(|V||E|) đồ thị biểu diễn danh sách cạnh Bài tập: Bài 1: Mê cung hình chữ nhật kích thước m×n gồm ô vuông đơn vị (m, n ≤ 1000) Trên ô ghi ba kí tự: • O: Nếu ô an toàn • X: Nếu ô có cạm bẫy • E: Nếu ô có nhà thám hiểm đứng Duy có ô ghi chữ E Nhà thám hiểm từ ô sang số ô chung cạnh với ô đứng Một cách thoát khỏi mê cung hành trình qua ô an toàn ô biên Hãy giúp cho nhà thám hiểm hành trình thoát khỏi mê cung qua ô Dữ liệu vào từ tệp văn MECUNG.INP • Dòng 1: Ghi m, n (1

Ngày đăng: 29/04/2017, 19:47

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan