Thuật toán A* tìm đường ngắn đồthị có thông tin định hướng Nguyễn Văn Sơn Để giải toán tìm đường đồthị có nhiều thuật toán Dijkstra, thuật toán Floy-Bellman Trong viết này, giới thiệu với bạn đọc thuật toán tiếng tìm đường ngắn đồthị có thông tin định hướng với tên gọi A* (đọc ″a sao″) Thuật toán dựa tư tưởng tìm kiếm heuristic áp dụng vào toán thực tế với với thông tin đặc biệt bổ sung ví dụ như: tồn cung với trọng số lớn tổng trọng số cung đồ thị, đồthị cung Thuật toán A* đặc biệt có hiệu áp dụng vào toán có kích thước lớn toán tìm đường mạng lưới giao thông có nhiều nút, toán tìm đường trò chơi chiến thuật với nhiều vật cản Điểm mấu chốt trình cài đặt thuật toán việc xác định xác thông tin ước lượng nhằm định hướng cho việc tìm kiếm Chẳng hạn, toán tìm đường thành phố thông tin ước lượng cho phép tìm đường tắt tránh vị trí hay bị tắc nghẽn; chương trình trò chơi, định hướng tới đích nhanh nhất, gặp vật cản men theo vật cản Nội dung thuật toán trình bày đây: Một số ký hiệu: - s: đỉnh xuất phát - t: đỉnh kết thúc (đích) - close: tập đỉnh tính xác đường ngắn - open: tập đỉnh lại - l[i,j]: trọng số cung (i,j) - d[i]: khoảng cách ngắn từ i đến s - v[i]: khoảng cách ngắn ước lượng từ i đến s Yêu cầu toán cần tìm giá trị d[t] Thuật toán A* d[i] = +∞ i với i thuộc [1 n] close= [s] open= [1 n] − [s] k=s repeat {sửa đổi ước lượng min} với i thuộc open d[i] = {d[i], d[k] +l[k,i]} {mở rộng tập close} chọn k thuộc open để (d[k] + v[k] ≤ d[i] + v[i]) với với i thuộc open open = open − [k] close = close + [k] until t thuộc close; Thuật toán Dijkstra d[i] = +∞với i thuộc [1 n] close= [s] open= [1 n] − [s] k=s repeat {sửa đổi ước lượng min} với i thuộcopen d[i] = {d[i], d[k] +l[k,i]} {mở rộng tập close} chọn k thuộc open để (d[k] ≤ d[i] ) vớivới i thuộcopen open = open − [k] close = close + [k] until t thuộc close; Sự khác biệt hai thuật toán điểm chọn đỉnh k để mở rộng tập close Việc lựa chọn đỉnh để mở rộng cho trình tìm kiếm đóng vai trò quan trọng chiến lược tìm kiếm Nếu ta lựa chọn đỉnh để phát triển tiếp với ước lượng tốt rút ngắn thời gian chi phí tính toán Cả hai thuật toán có độ phức tạp O(n2) Người ta chứng minh trọng số đồthị dương (l[i,j]>0 với i,j) v[i] ước lượng dương bé so với đường ngắn từ i tới u (0< v[i] 1 then Begin Down(u,v,i,j); If ktr(front,top,v) then Begin So_pts:=so_pts+1; P[so_pts]:=v;End End; If j>1 then Begin Right(u,v,i,j); If ktr(front,top,v) then Begin So_pts:=so_pts+1;P[so_pts]:=v End End; If j If ktr(front,top,v) then Begin So_pts:=so_pts+1; P[so_pts]:=v; End End; If I If ktr(front,top,v) then Begin So_pts:=so_pts+1;P[so_pts]:=v;End End; End; PROCEDURE Sxep(Var P:node1;so_pts:tp); Var Tg :vec; T,i,j,min :tp; B :array[1 4] of byte; Begin For i:=1 to so_pts B[i]:=count(p[i]); For i:=1 to so_pts-1 Begin Min:=i; For j:=i+1 to so_pts If b[j] If min>i then Begin T:=b[i]; B[i]:=b[min];B[min]:=t; Tg:=p[i];P[i]:=p[min];P[min]:=tg; End End End; PROCEDURE Push(var top:pointer;p:node1;child:longint;so_pts:tp); Var i:tp;v:pointer; Begin For i:=so_pts downto Begin New(v); V^.infor.ma:=p[i]; V^.infor.father:=child; Id:=id+1; V^.infor.child:=id; V^.next:=top; Top:=v;End End; PROCEDURE In_Kq; Var p :pointer;i,buoc :longint; Begin Buoc:=0; P:=front;I:=1; assign(ff,fo); rewrite(ff); if not found then begin write(ff,0); close(ff); exit; end; P:=p^.next; While Pnil Begin If p^.infor.father=i then Begin I:=p^.infor.child; Buoc:=buoc+1; Writeln(ff,buoc);In_vec(P^.infor.ma); End; P:=p^.next End; close(ff); End; Begin Clrscr;Init; While (topnil) and not(Found) Begin Pop(Top,U); Ađ(u,Rear,Front); If dung(u.ma,dich) then found:=true Else Begin Vi_tri(U.ma,i,j); So_pts:=0; Ptu_ke(p,u.ma,i,j,so_pts); sxep(p,so_pts);Push(top,p,u.child,so_pts) End End; In_kq; End Bài tập: Cho ma trận nhị phân (các số hay 1) kích thước 500 x 500 Hai ô gọi kề chúng chứa số chung cạnh Hai ô gọi đến chúng đến qua số bước dịch chuyển qua ô kề nhau, số bước dịch chuyển độ dài đường tìm đường ngắn từ ô (x1,y1) tới ô (x2,y2) ... tính toán Cả hai thuật toán có độ phức tạp O(n2) Người ta chứng minh trọng số đồ thị dương (l[i,j]>0 với i,j) v[i] ước lượng dương bé so với đường ngắn từ i tới u (0< v[i]