Thuật toán Dịjkastra cải tiến

5 894 19
Thuật toán Dịjkastra cải tiến

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

Thông tin tài liệu

Thuật toán Dịjkastra cải tiến

Thuật toán Dijkstra với những cải tiếnduccanh841988@yahoo.comThuật toán Dijkstra là một thuật toán tốt và hiệu quả trong việc tìm đường đi ngắn nhất trên đồ thị trong trường hợp trọng số trên các cung không âm. Quả thực thuật toán đã được đề cập rất nhiều, nhưng ở đây mình xin giới thiệu một cải tiến mới.Xét bài toán 1: cho đồ thị G=(V,E), hãy tìm đường đi ngắn nhất từ đỉnh xuất phát s tới đỉnh đích f.Lời giải: đây là một bài toán kinh điển của thuật toán Dijkstra:d[i] = + ∞ với mọi I thuộc [1 n]Đánh dấu đỉnh s. d[s]=0. repeat {tìm 1 đỉnh k còn tự do và có trọng số d[k] nhỏ nhất.} {nếu k=f thì dừng} {Đánh dấu đỉnh k.} với mọi đỉnh I còn tự do thì d[i] = min {d[i], d[k] +l[k,i]} until {mọi đỉnh đều bị đánh dấu }; Bây giờ ta sẽ xét ví dụ 1: Cho 1 hình chữ nhật (NxM) mỗi ô là 1 số nguyên. Từ 1 ô (x,y) hãy tìm đường đi đến ô (u,v) sao cho tổng các số ghi trên các ô là bé nhất (qui tắc đi: từ 1 ô chỉ đi được đến các ô có chung cạnh). Lời giải: Đây là 1 bài toán quen thuộc và có thể dùng nhiều cách giải khác nhau, nhưng ở đây chúng ta chỉ xét cách giải bằng thuật toán Dijkstra: Gọi a[I,j] là trọng số nhỏ nhất khi đi từ ô (x,y) đến ô (I,j). Khi đó cài đặt thuật toán trên ta sẽ tìm ra a[u,v] là trọng số nhỏ nhất của đường đi từ (x,y) đến (u,v). Vấn đề ở đây là khi tìm 1 đỉnh k tự do và có trọng số nhỏ nhất ta phải dùng 1 vòng for lồng nhau để duyệt hết bảng, trong khi có rất nhiều ô tự do có giá trị bằng + ∞ và nhiều ô đã được cố định nhãn.Vì vậy ở đây ta có thể cải tiến dùng thêm 2 mảng 1 chiều để giữ lại các ô tự do mà có giá trị a[I,j] + ∞. Việc này có ý nghĩa rất lớn trong việc tìm kiếm ô tự do có giá trị min. Ví dụ: xuất phát từ ô (1,3) đến ô (3,1). Tổng chi phí của đường đi ngắn nhất là 20. Nếu dùng Dijkstra bình thường thì mỗi lần tìm min ta phải duyệt hết, nhưng nếu ta chỉ tìm những ô đang tự do mà có giá trị khác + ∞ thời gian chạy chương trình sẽ nhanh hơn. Quá trình chạy theo bảng sau: Những ô màu xanh và đỏ là những ô thuộc vùng tìm kiếm giá trị min,ô màu đỏ là ô có giá trị min trong bước chạy đó, những ô màu đen là những ô không thuộc vùng tìm kiếm giá trị min. Ta có thể thấy số ô trong vùng tìm kiếm (ô màu xanh và đỏ) ít hơn rất nhiều so với ô màu đen. Chương trình dưới đây dùng mảng q:array[1 2,1 1000] of byte để giữ lại chỉ số các ô trong vùng tìm kiếm. uses crt;const fi='vd1.inp';fo='vd1.out';max=100;maxa=10000;interval=1193180/65536; dx:array[1 4]of integer=(1,0,-1,0);dy:array[1 4]of integer=(0,-1,0,1);var a,c:array[1 max,1 max]of word;trace:array[1 max,1 max]of byte;free:array[0 max,0 max]of boolean;q:array[1 2,1 2000]of byte;m,n,x,y,u,v,top:integer;sttime:longint;time: longint absolute 0:$46c;procedure nhap;var f:text;i,j:integer;beginassign(f,fi);reset(f);readln(f,n,m,x,y,u,v);for i:=1 to n dobeginfor j:=1 to m do read(f,c[i,j]);readln(f);end;close(f);sttime:=time;end;procedure init;var i,j:integer;beginfillchar(free,sizeof(free),false);for i:=1 to n dofor j:=1 to m dobegina[i,j]:=maxa;free[i,j]:=true;end;end;procedure ijk;var i,j,min,k,h:integer;begina[x,y]:=c[x,y];top:=1;q[1,top]:=x;q[2,top]:=y;repeat min:=maxa;for i:=1 to top doif(a[q[1,i],q[2,i]]a[k,h]+c[k+dx[i],h+dy[i]]) thenbegina[k+dx[i],h+dy[i]]:=a[k,h]+c[k+dx[i],h+dy[i]];trace[k+dx[i],h+dy[i]]:=i;inc(top);q[1,top]:=k+dx[i];q[2,top]:=h+dy[i];end;until false;end;procedure xuat;var i,j,k:integer;f:text;beginassign(f,fo);rewrite(f);writeln(f,a[u,v]);i:=u;j:=v;while (ix)or(jy)dobeginwriteln(f,'(',i,',',j,')');k:=trace[i,j];i:=i-dx[k];j:=j-dy[k];end;writeln(f,'(',i,',',j,')');write(f,(time-sttime)/interval:1:10);close(f);end;procedure test;var i,j:integer;f:text;beginassign(f,fi);rewrite(f);writeln(f,'100 100 1 1 100 100');randomize;for i:=1 to 100 dobeginfor j:=1 to 100 dowrite(f,random(20),' '); writeln(f);end;close(f);end;beginnhap;init;ijk;xuat;end.Nếu ta tính thời gian chạy thì chương trình trên chạy bộ test cỡ n=100, m=100, x=1, y=1, u=100, v=100 thì nhanh hơn chương trình Dijkstra rất nhiều (theo mình thử thì mất khoảng 0,055s, trong khi Dijkstra bình thường mất khoảng 2 s). Đối với các bài toán có áp dụng Dijkstra (như bài toán 1) thì ta có thể áp dụng cái tiến trên để chương trình có thể chạy nhanh hơn. Các bạn hãy thử sức với bài toán sau: Cho một ma trận nhị phân kích thước 200X200. Hai ô chứa số 0 và có chung cạnh gọi là 2 ô kề nhau. Hai ô đến được nhau nếu chúng có thể đến được nhau qua 1 số ô kề nhau, số bước dịch chuyển là độ dài của đường đi.Từ 1 ô (x,y) hãy tìm đường đi ngắn nhất đến một ô bất kì nằm sát biên của ma trận . Thuật toán Dijkstra với những cải tiếnduccanh841988@yahoo.comThuật toán Dijkstra là một thuật toán tốt và hiệu quả trong việc. các cung không âm. Quả thực thuật toán đã được đề cập rất nhiều, nhưng ở đây mình xin giới thiệu một cải tiến mới.Xét bài toán 1: cho đồ thị G=(V,E), hãy

Ngày đăng: 11/09/2012, 15:00

Hình ảnh liên quan

Quá trình chạy theo bảng sau: - Thuật toán Dịjkastra cải tiến

u.

á trình chạy theo bảng sau: Xem tại trang 2 của tài liệu.

Từ khóa liên quan

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

Tài liệu liên quan