1. Trang chủ
  2. » Công Nghệ Thông Tin

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

5 897 19
Tài liệu đã được kiểm tra trùng lặp

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

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 5
Dung lượng 46 KB

Nội dung

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

Trang 1

Thuật toán Dijkstra với những cải tiến

duccanh841988@yahoo.com

Thuậ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)

Trang 2

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;

Trang 3

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;

begin

assign(f,fi);

reset(f);

readln(f,n,m,x,y,u,v);

for i:=1 to n do

begin

for j:=1 to m do read(f,c[i,j]);

readln(f);

end;

close(f);

sttime:=time;

end;

procedure init;

var i,j:integer;

begin

fillchar(free,sizeof(free),false); for i:=1 to n do

for j:=1 to m do

begin

a[i,j]:=maxa;

free[i,j]:=true;

end;

end;

procedure ijk;

var i,j,min,k,h:integer;

begin

a[x,y]:=c[x,y];

top:=1;

q[1,top]:=x;

q[2,top]:=y;

repeat

Trang 4

for i:=1 to top do

if(a[q[1,i],q[2,i]]a[k,h]+c[k+dx[i],h+dy[i]]) then begin

a[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;

begin

assign(f,fo);

rewrite(f);

writeln(f,a[u,v]);

i:=u;

j:=v;

while (ix)or(jy)do

begin

writeln(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;

begin

assign(f,fi);

rewrite(f);

writeln(f,'100 100 1 1 100 100');

randomize;

for i:=1 to 100 do

begin

for j:=1 to 100 do

write(f,random(20),' ');

Trang 5

end;

close(f);

end;

begin

nhap;

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

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: (Trang 2)

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w