Sưu tầm bởi:
www.daihoc.com.vn
Thiết kế và đánh giá thuật toán - 81 -
CHƯƠNG 5: PHƯƠNG PHÁP THAM LAM
(The greedy method)
I. Mở đầu
1. Ý tưởng
Phương pháp tham lam là kỹ thuật thiết kế thường được dùng để giải các bài
u cho bài
øi toán được bổ sung dần từng bước từ lời giải
øi toán ?
ược ằng p ương háp tham lam thường chỉ là chấp nhận
on S của
. Với một tập con S được chọn ra thỏa mãn các yêu cầu của bài toán, ta gọi là một
ghiệm i áp nha được với
nghiệm chấp nhận được mà tại đó hàm mục tiêu đạt
Đặc trưng tham lam của phương pháp thể hiện bởi : trong mỗi bước việc xử
ốt có thể xảy
toán tối ưu. Phương pháp được tiến hành trong nhiều bước. Tại mỗi bước, theo một
chọn lựa nào đó ( xác đònh b
ằng một hàm chọn), sẽ tìm một lời giải tối ư
toán nhỏ tương ứng. Lời giải của ba
của các bài toán con.
Lời giải được xây dựng như thế có chắc là lời giải tối ưu của ba
Các lời giải tìm đ b h p
được theo điều kiện nào đó, chưa chắc là tối ưu.
Cho trước một tập A gồm n đối tượng, ta cần phải chọn một tập c
A
n chấp nhận được . Một hàm mục t êu gắn mỗi nghiệm cha än
một giá trò. Nghiệm tối ưu là
giá trò nhỏ nhất ( lớn nhất).
lí sẽ tuân theo một sự chọn lựa trước, không kể đến tình trạng không t
ra khi thực hiện lựa chọn lúc đầu.
2. Mô hình
Chọn S từ tập tập A .
Chọn hần tư tốt nhất của A gán va x : x Chọn
- Nếu S
∪ {x} thỏa mãn yếu cầu bài toán thì
greedy (A,n)
≡
S =
∅;
= A-{x}
if( S
∪ {x} chấp nhận được )
S = S
∪ {x};
Tính chất tham lam của thuật toán đònh hướng bởi hàm Chọn.
- Khởi động S =
∅;
Trong khi A
≠ ∅:
-
- p û øo = (A) ;
- Cập nhật các đối tượng để chọn : A = A-{x};
Cập nhật lời giải : S = S∪ {x};
ó thể cài đặt như sau : Thủ tục thuật toán tham lam c
input A[1 n]
output S //lời giải;
while ( A
≠ ∅)
{
x= Chọn(A);
A
}
Trần Tuấn Minh Khoa Toán-Tin
Simpo PDF Merge and Split Unregistered Version -
Sưu tầm bởi:
www.daihoc.com.vn
Thiết kế và đánh giá thuật toán - 82 -
1
2
return S;
I. Ba toán ườ
I øi ng i du lòch
1. toB ánài
Một ngøi lòch muốn tham quan n thành phố
ời du
du T , , T . Xuất phát từ mộ
1 n
t
ành p hố còn lại, mỗi
ành p
ij
tìm một hành trình thỏa yêu
2. Ý tưởng
th hố nào đó, ngư lòch muốn đi qua tất cả các thành p
ái quay trở lại thành phố xuất phát. th hố đi qua đúng 1 lần ro
C Gọi
là chi phí đi từ thành phố T
i
đến T
j
. Hãy
cầu bài toán sao cho chi phí là nhỏ nhất.
hất trong một đơn đồ thò có
toán tham lam cho bài toán là chọn thành phố có chi phí nhỏ nhất tính
a qua.
3. Thuật toán
Đây l ø bài toán tìm chu trình có trọng số nhỏ na
hướng có trọng số.
Thuật
từ thành phố hiện thời đến các thành phố chư
1
5 2
3 4 4
5 2
3 7 3
put
ành trình tối ưu,
hỏ nhất tính từ TP v đến
ập nhật lời giải
vw
; //Cập nhật chi phí
C =
⎦
⎢
⎢
03235
21042
In C= (C
ij
)
output TOUR //H
COST;//Chi phí tương ứng
Mô tả :
TOUR := 0; COST := 0; v := u; // Khởi tạo
∀k := 1 → n ://Thăm tất cả các thành phố
// Chọn cạnh kế )
- Chọn <v, w> là đoạn nối 2 thành phố có chi phí n
các thành phố chưa qua.
- TOUR := TOUR + <v, w>; //C
- COST := COST + C
// Chuyến đi hoàn thành
TOUR := TOUR + <v, u>;
COST := COST + C
vu
;
Minh ho
ạ :
⎥
⎥
⎢
⎢
⎣
30147
⎥
⎥
⎥
⎥
⎢
⎢
34401
⎤
⎡
57210
Trần Tuấn Minh Khoa Toán-Tin
Simpo PDF Merge and Split Unregistered Version -
Sưu tầm bởi:
www.daihoc.com.vn
Thiết kế và đánh giá thuật toán - 83 -
2
1
2
2
3
2
5 3
3
<
,<4,1>}
1. TOUR := 0; COST := 0; u := 1; 1
⇒ w = 2; 1
2. TOUR := <1,2>; COST := 1; u := 2;
⇒ w = 5; 1
5 3
3. TOUR := {<1,2>, <2,5>}
COST := 4; u := 5;
1
⇒ w = 3; 1
5 3
4. TOUR := {<1,2>, <2,5>,<5,3>} 2
COST := 6; u := 3;
1
⇒ w = 4; 1
2
4 1
OUR := {<1,2>, 2,5>,<5,3>,<3,4>} 5. T
COST := 7; u = 1;
TOUR := {<1,2>, <2,5>,<5,3>,<3,4>
COST := 14
4. Độ phức tạp của thuật toán
Thao tác chọn đỉnh thích hợp trong n đỉnh được tổ chức bằng một vòng lặp
øng lặp lồng nhau, nên
n
2
).
5. Cài đa
để duyệt. Nên chi phí cho thuật toán xác đònh bởi 2 vo
T(n)
∈ O(
ët
int GTS (mat a, int n, int TOUR[max], int Ddau)
Trần Tuấn Minh Khoa Toán-Tin
Simpo PDF Merge and Split Unregistered Version -
Sưu tầm bởi:
www.daihoc.com.vn
Thiết kế và đánh giá thuật toán - 84 -
{
int daxet[max]; //Danh dau cac dinh da duoc su dung
(k = 1; k <= n; k++)
duoc xet
COST tri COST == 0
u n d g
1
= VC;
for (k = 1; k <= n; k++)
if(mini > a[v][k])
{
đi ngắn nhất trong đồ thò có
int v, //Dinh dang xet
k, //Duyet qua n dinh de chon
w; //Dinh duoc chon trong moi buoc
int mini; //Chon min cac canh(cung) trong moi buoc
int COST; //Trong so nho nhat cua chu trinh
for
daxet[k] = 0; //Chua dinh nao
= 0; //Luc dau, gia
int i; // Bien dem, dem tim d inh thi dun
v = Ddau; //Chon dinh xuat phat la
i = 1;
TOUR[i] = v; //Dua v vao chu trinh
daxet[v] = 1; //Dinh v da duoc xet
while(i < n)
{
mini
if(!daxet[k])
mini = a[v][k];
w = k;
}
v = w;
i++;
TOUR[i] = v;
daxet[v] = 1;
COST += mini;
}
COST += a[v][Ddau];
return COST;
}
I h oán DII. T uật t ijkstra -Tìm đường
t srọng ố
1. Bài toán
(vô hướng hoặc có hướng) có trọng
,
V = {1
Cho G = (V,E) là đơn đồ thò liên thông
số
, , n} là tập các đỉnh , E là tập các cạnh (cung).
Trần Tuấn Minh Khoa Toán-Tin
Simpo PDF Merge and Split Unregistered Version -
Sưu tầm bởi:
www.daihoc.com.vn
Thiết kế và đánh giá thuật toán - 85 -
Cho s
0
∈ E. Tìm đường đi ngắn nhất đi từ s
0
đến các đỉnh còn lại.
rên bằng thuật toán Dijkstra .
2.
Giải bài toán t
Ý tưởng
Th ouật t án Dijkstra cho phép tìm đường đi ngắn nhất từ một đỉnh s đến các
số ) tương ứng.
tự đỉnh có chiều dài đến s theo
mỗi đỉnh các nhãn tạm thời.
àu dài đường đi ngắn nhất từ s
ớc lặp, mà ở mỗi bước lặp
chính thức. Nếu nhãn của một đỉnh nào đó trở
thành c đi từ s đến
đỉnh đó.
3.
đỉnh còn lại của đồ thò và chiều dài (trọng
Phương pháp của thuật toán là xác đònh tuần
thứ tự tăng dần.
Thuật toán được xây dựng trên cơ sở gán cho
Nhãn tạm thời của các đỉnh cho biết cận trên của chie
đến đỉnh đó. Nhãn của các đỉnh sẽ biến đổi trong các bư
sẽ có một nhãn tạm thời trở thành
hính thức thì đó cũng chính là chiều dài ngắn nhất của đường
Mô tả thuật toán
Ký hiệu :
* L(v) để chỉ nhãn của đỉnh v, tức là cận trên của chiều dài đường đi ngắn
s
0
đến v.
án n-1 đỉnh
òn lại
input
Output : d(s ,v
Mô tả
Khởi động :
õn chính thức
S = {s
0
}; // s có Nhãn chính thức
1:
- T thơ ), v
∉
s
0
L(v) = Min{L(v), L(s
0
) + m(s
0
,v)};
-
∉ S và kề với sao cho :
) = Min{L(v) : ∀v ∉ };
(Khi đó : d(s
0
,s
1
) = L(s
1
)
// S = {
1
} ; s
1
ó nhãn hính t ùc
2
- Tính lại nhãn tạm thời L(v), v
∉ S :
áu v kề với s
1
thì
nhất từ s
0
đến v.
* d(s
,v) : chiều dài đường đi ngắn
0
nhất từ
* m(s
0
,v) là trọng số của cung (cạnh) (s,v).
Thuật toán Dijkstra tìm chiều dài đường đi ngắn nhất từ đỉnh s đe
c đ ô tả như sau : ược m
: G, s
0
), ∀v ≠ s ;
0 0
:
•
L(v) =
∞ , ∀v ≠ s
0
; //Nhãn tạm thời
S =
∅; //Tập lưu trử các đỉnh có nha
• 0 : Bước
d(s
0
,s
0
) = L(s
0
) = 0;
0
• Bước
ính lại nhãn tạm
Nếu v kề với
øi L(v
S :
thì
Tìm s
1
s
0
L(s
1
S,
)
- S = S
∪ {s
1
}; s
0
, s c c hư
• Bước :
Ne
L(v) = Min{L(v), L(s
1
) + m(s
1
,v)};
Trần Tuấn Minh Khoa Toán-Tin
Simpo PDF Merge and Split Unregistered Version -
Sưu tầm bởi:
www.daihoc.com.vn
Thiết kế và đánh giá thuật toán - 86 -
- Tìm s
2
∉ S và kề vơ o cho :
L(s
∀v ∉ S};
d(s,s
2
) = L(s
2
) ); //0 = d(s
0
,s
1
) ≤ d(
0
,s
2
)
Nếu L(s
2
) = Min{L(s
j
), L(s
j
) + m(s
j
,s
2
)} thì đường đi từ s đến s
2
đi qua đỉnh
j
là
ng
2 0 1 2 2
i-1 i-1
j
, j =
ùi s
1
hoặc s
0
sa
2
) = Min{L(v) :
( Khi đó :
s
s
ắn nhất, và s
j
là đỉnh đứng kề trước s
2
.
- S = S
∪ {s }; // S = {s , s , s } ; //s có nhãn chính thức
. . .
• Bước i:
- Tính lại nhãn tạm thời L(v), v
∉ S :
Nếu v kề với s
i-1
thì
L(v) = Min{L(v), L(s
) + m(s ,v)};
- Tìm s
i
∉ S và kề với s 1,0 −i sao cho :
( d(s,s
i
= d(s,s
1
) ≤ d(s,s
2
) ≤ . . ≤ d(s,s
i
)
Nế (
qua đỉnh s
j
- S = S
∪ {s
i
};
i
}; //s
i
có nhãn chính thức
Thu
Khi thuật toán d(s
0
,s
0
) ≤ d(s
0
,s
1
) ≤ d(s
0
,s
2
) ≤ . . ≤ d(s
0
,s
n-
đến t, thì thuật toán dừng khi có t
∈
S.
lam của thuật toán Dijkstra là tại mỗi bước, chọn s
i
∉ S và s
i
L(s
i
) = Min{L(v) : ∀v ∉ S };
) = L(s
i
) ); //0
u L s
i
) = Min{L(s
j
), L(s
j
) + m(s
j
,s
i
)} thì đường đi ngắn nhất từ s đến s
i
đi
, và s
j
là đỉnh đứng kề trước s
i
.
// S = {s
0
,s
1
, ,s
ật toán dừng khi i = n-1;
kết thúc, ta có : 0 =
1
)
Nếu chỉ tìm đường đi ngắn nhất từ s
0
Tính chất tham
là đỉnh kề với s
j
, với j = 1,0 −i sao cho L(s
i
) = Min{L(v) : ∀v ∉ S }.
Minh hoạ : Xét đồ thò có hướng G :
20
45
h s = 1 đến các đỉnh còn lại :
10 80
90
15 18 40
36
10 30 4 15
4
5 2
15
4
20
6
10
3
1
Đường đi ngắn nhất từ đỉn
Trần Tuấn Minh Khoa Toán-Tin
Simpo PDF Merge and Split Unregistered Version -
Sưu tầm bởi:
www.daihoc.com.vn
Thiết kế và đánh giá thuật toán - 87 -
Bước 0 :
L(s ) =
∞; ∀s
d(1,1) = L(1) = 0;
và kề với 1 là 2,3,5 :
(2) = Min{ L(2), L(1)+m(1,2)} = 20.
L(1)+m(1,3)} = 15.
m(1,5)} = 80.
ề với 1 là 4,6 :
Tìm s
∉ S v kề vơ
S} = 15.
ong tất cả các
S = S
{3}; // S = {1,3}
2 :
Các đ nh
∉ S
m(3,2)} = Min{ 20, 15+4} = 19.
∞, 15+10} = 25.
ớc 1.
hoặc 3 sao cho :L(s
1
) = Min{L(v) : ∀v ∉ S };
19.
i : 1
→ 3→ 2 là ngắn nhất trong tất cả các
L(2) = 19.
S = S
Chiều dài của đường đi ngắn nhất
từ đỉnh s (=1) đến các đỉnh khác : tsnn[]
S = {1};
Bước 1 :
- Tính nhãn tạm thời L(v), v
∉ S :
* Các đỉnh
∉ S
L
L(3) = Min{ L(3),
L(5) = Min{ L(5), L(1)+
* Các đỉnh
∉ S và không k
L(4) = L(6) = ∞.
-
1
à ùi 1 sao cho :L(s
1
) = Min{L(v) : ∀v ∉ S };
L(3) = Min{L(v) :
∀v ∉
Đường đi từ 1 đến 3 xác đònh bởi : 1 → 3 là ngắn nhất tr
đường đi từ 1 đến các đỉnh khác và d(1,3) = L(3) = 15.
-
∪
Bước
- Tính nhãn tạm thời L(v), v
∉ S :
* ỉ
và kề với 3 là 2,6 :
L(2) = Min{ L(2), L(3)+
L(6) = Min{ L(6), L(3)+m(3,6)} = Min{
L(4) =
∞.
L(5) = 80 //Đã tính ở bư
- Tìm s
2
∉ S và kề với 1
L(2) = Min{L(v) :
∀v ∉ S} = Min{ L(2), L(3)+m(3,2)} =
Đường đi từ 1 đến 2 xác đònh bở
đường đi từ 1 đến các đỉnh j
≠ 3 và : d(1,2) =
-
∪ {2}; // S = {1,3,2}
. . . tương tự, ta có kết quả tính toán sau đây :
Đường đi ngắn
đến
1 2 3 4 5 6
Bước
lặp
nhất là đường đi
đỉnh
từ đỉnh 1
Bước1 1→ 3 3 - 20 15
∞
80
∞
Bước2 1→3→ 2 2 - 19 - 25
Bước3 1→3→ 6 6 - - - 29 25
Bước4 1→3→ 6→4 4 - - - 29 -
Bước5 1→3→ 2→5 5 - - - - 29 -
4. Cài đặt
- Ta biểu diễn đơn đồ thò có hướng G bằng ma trận các trọng số của cạnh :
Trần Tuấn Minh Khoa Toán-Tin
Simpo PDF Merge and Split Unregistered Version -
Sưu tầm bởi:
www.daihoc.com.vn
Thiết kế và đánh giá thuật toán - 88 -
a= (a
uv
)
nxn
;
trong đó :
⎩
⎨
⎧
∉∞
∈
=
;),(;
;),();,(
Evu
Evuvusngtr
a
uv
củao
á
ọ
, ký hiệu là
[ ].
đưa vào tập S thì ta gán Daxet[k]
= 1; và khi đó L[k] là nhãn chính thức của k ( chỉ chiều dài của đường đi nhỏ nhất
Daxet[i] = 0,
∀i.
h nhãn tạm thời ) bằng
∞ .
L[i] =
∞; i ≠ s.
ø đỉnh vừa đưa được vào S, Daxet[Dht] = 1
), các đỉnh i chưa được xét sẽ được đánh nhãn lại như sau :
Dht
(đó là đ
đường đi ngắn nhất từ s đến t, với t
∈ S , ta dùng
mảng m i.
Inpu
ngắn nhất từ s đến các đỉnh còn lại
ùng
{
øn t tại mỗi bước
Daxet[i] = 0;
- Dùng mảng 1 chiều để lưu trử các nhãn tạm thời của các đỉnh
L
- Dùng mảng 1 chiều Daxet[ ] các giá trò logic để đánh dấu các đỉnh đã được
đưa vào tập S ( gồm các đỉnh có nhãn chính thức ):
Mỗi bước, nếu xác đònh được đỉnh k để
của đường từ s đến k) .
- Khởi động dữ liệu :
o Khởi động Daxet[] là rổng :
o Khởi động cận trên chiều dài của đường đi ngắn nhất từ s đến đỉnh
khác ( đán
o Khởi động trọng số nhỏ nhất đường đi từ s đến s bằng 0.
L[s] = 0;//d(s,s) = 0
- Giả sử tại mỗi bước, ( với Dht la
Nếu (L[i] + m(Dht,i) ) < L[i]) thì :
L[i] = L[Dht] + m(Dht,i);
Và trong trường hợp này, đường đi ngắn nhất từ s đến i sẽ đi qua đỉnh
ỉnh kề trước i)
- Để lưu trử các đỉnh trên
ột chiều Ddnn[ ], với tính chất Ddnn[i] là đỉnh trước đỉnh
Thuật toán được cài đặt bằng hàm sau :
t a[n][n], s
Output - Xuất ra màn hình đường đi
- Chiều dài tương ư
void dijkstra( int s)
int Ddnn[max]; // Chứa g đi ngắn nhất từ s đến đỉnh
int i,k,Dht,Min;
đươ
int Daxet[max]; //Đánh dấu các đỉnh đã đưa vào S
int L[max];
for ( i = 1; i <= n; i++)
{
L[i] = VC;
Trần Tuấn Minh Khoa Toán-Tin
Simpo PDF Merge and Split Unregistered Version -
Sưu tầm bởi:
www.daihoc.com.vn
Thiết kế và đánh giá thuật toán - 89 -
}
//Dua dinh s vao tap dinh S da xet
Daxet[s] = 1;
int h = 1; //đếm mỗi bước : cho đủ n-1 bước
hile ( = n-1)
{
=
for ( i = 1; i <= n; i++)
if(!Daxet[i])
{
{
L[i] = L[dht] + a[dht][i] ;
dht;
//gan dinh hien tai la dinh truoc dinh i tren lo
inh
}
if(L[i] < Min) // Chon đỉnh k
{
in = L[i];
k = i;
}
}
ng đi ngắn nhất từ s đến k : Ddnn[]
xuatdd(s,k,Ddnn);
cout<< ng so
dht = k;//
Daxet[dht] = 1; a nut k vao t da xet
h++;
}
****************** *******
oid xuatdd(int s, int k, Ddnn[m
int
Duong di ngan nhat tu "<<s<<" den "<<k<<" la : ";
cout<<i<<"< ";
i = Ddnn[i];
}
L[s] = 0;
Dht = s;
w h<
Min VC;
if ( L[dht] + a[dht][i] < L[i] ) //Tính lại nhãn
Ddnn[i] =
tr
M
// Tại bước h : tìm được đườ
"\nTro : "<<L[k];
Khoi dong lai Dht
//Du tap nu
}
// **
v int ax])
{
i;
cout<<"\n
i = k;
while(i != s)
{
Trần Tuấn Minh Khoa Toán-Tin
Simpo PDF Merge and Split Unregistered Version -
Sưu tầm bởi:
www.daihoc.com.vn
Thiết kế và đánh giá thuật toán - 90 -
cout<<s;
}
5. Độ phức tạp của thuật toán
Thuật toán mô tả bởi 2 vòng lặp lồng n
2
hau, nên T(n) ∈ O(n ).
IV. Thuật toán Prim – Tìm cây bao trùm nhỏ nhất (Minimal Spanning
Tree)
1. Bài toán
G = (V,E) là đơn đồ thò vô hướng liên thông, có trọng số .
V = {1, ,n}là tập các đỉnh. E là tập các cạnh (edge).
Một cây T gọi là cây bao trùm của G nếu T là đồ thò con của G và chứa mọi
đỉnh của G.
Vấn đề là tìm cây bao trùm có trọng số nhỏ nhất : MST (Minimal
anning Tree ) của G.
giải bài toán trên là các thuật toán Prim và Kruscal.
äu thuật toán Prim
Sp
Các thuật toán cơ bản
Trong phần này, ta giới thie
2. Ý tưởng
T oán Prim xây dựng mo
ỉnh cu
huật t ät đồ thò con T của G như sau:
ầu tie ûa G đặt vào T.
iện trong khi T chưa chứa hết các đỉnh của G :
ó trọng số nhỏ nhất nối 1 đỉnh trong T với 1 đỉnh
ính th a Prim là tại mỗi bước thêm vào T một cạnh có
ät đỉnh goài T.
3. ô tả huật
Đ ân chọn tuỳ ý 1 đ
Q nh sau còn thực huá trì
Mỗi bước, tìm một cạnh c
øy vào T. ngoài T. Thêm cạnh na
Kết thúc thuật toán Prim cho ta một MST của đồ thò G.
T am lam của thuật to ùn
trọng số nhỏ nhất nối một đỉnh trong T và mo n
M t toán
nput G = (V,E)
Output T = (V, .) là MST
Mô tả :
- Gọi U là tập con của V.
- on rổng.
đỉnh 1 đặt vào T.
-
ìm ca hỏ nhất, với u
∈U và v ∉ U. Thêm đỉnh v
lời giải tối ưu.
Khởi động T = (U,.) = ∅; //Đồ thò c
- Khởi động U = {1}; // Chọn
Trong khi ( U ≠ V )
T ïnh (u,v) có trọng số n
này vào U. Thêm (u,v) vào T .
Lời giải của bài toán là
Minh họa :
Xét đồ thò sau :
Trần Tuấn Minh Khoa Toán-Tin
Simpo PDF Merge and Split Unregistered Version -
Sưu tầm bởi:
www.daihoc.com.vn
Thiết kế và đánh giá thuật toán - 91 -
1 2
5 6
thò trên :
2 3 3
động của thu toán :
Bư Các
1 2 3
4 6 4
3 8
4 7 3
4 5 6
7
Áp dụng thuật toán Prim,bắt đầu từ đỉnh 1,ta xây dựng dần 1 MST của đồ
4 4
1
2
4
5
7
6
3
Hoạt ật
ớc cạnh chọn Tập U
3
0 - {1}
1 (2,1 {1,2
) }
2 (3,2) {1,2,3}
3 (4,1) {1,2,3,4}
4 (5,4) {1,2,3,4,5}
5 (7,4) {1,2,3,4,5,7}
6 (6,7) {1,2,3,4,5,7,6}
4. Cài đặt
Để tiến hành cài đặt thuật toán, ta cần mô tả dữ liệu .
Đồ thò rận kề của nó :
c = (c[i][j])
nxn
.
có trọng số có thể biểu diễn bởi 1 ma t
Trần Tuấn Minh Khoa Toán-Tin
Simpo PDF Merge and Split Unregistered Version -
Sưu tầm bởi:
www.daihoc.com.vn
Thiết kế và đánh giá thuật toán - 92 -
⎪
⎩
⎪
⎧
∞
==
;(;
;0
;);,(
]][[
tainotngokhiueN
ji
ueNjiosngTr
jic
)))
⎨
),
),(
j
tainotji
)
)
)
ọ
Khi tìm cạnh có trọng số nhỏ nhất
tại mỗi bước, ta sẽ
nối 1 đỉnh trong U và một đỉnh ngoài U
ảng lowcost để tìm đỉnh closest[k]
∈ U sao cho
lo
loses và lowcost ,và có k đã thêm vào U.
hi ma đỉnh k cho cây bao trùm, ta cho lowcost[k] =
∞, là một giá
vậy đỉnh này sẽ
Closest[i] = 1;
{
cost[2];
ost[j] < Min )
Min = Lowcost[j];
;
sest[k];
g l
r ( j=2; j<=n; j++)
c[k][ j] < lowcost[j]) && (lowcost[j] <
∞))
{
lowcost[j] = c[k][j];
closest[j] = k;
}
dùng 2 mảng để lưu trử :
- Mảng closest [ ] : // == U
Với i
∈ V\U thì closest[i] ∈ U là đỉnh kề gần i nhất.
- Mảng lowcost[i] cho trọng số của cạnh (i, closest[i]) .
Tại mỗi bước, ta duyệt m
trọng số (k,closest[k]) = wcost[k] là nhỏ nhất. Khi tìm được, Ta in cạnh
(c t[k], k), cập nhật vào các mảng closest
K ø ta tìm được một
trò rất lớn, lớn hơn bất kỳ trọng số của cạnh nào của đồ thò, như
không được kéo dài trong U.
void Prim (Mat c)
{
double Lowcost[MAX];
int Closest[MAX];
int i,j,k,Min;
for (i=2;i<=n;i++)
{
Lowcost[i] = c[1][i];
}
for (i=2;i<=n;i++)
Min = Low
k = 2;
for ( j=3; j<=n; j++) // Chọn k
if (Lowc
{
k = j
}
cout<<endl<<k<<clo
lowcost[k] =
∞;
// Khởi độn ại Closest[], Lowcost[]
fo
if ( (
Trần Tuấn Minh Khoa Toán-Tin
Simpo PDF Merge and Split Unregistered Version -
Sưu tầm bởi:
www.daihoc.com.vn
Thiết kế và đánh giá thuật toán - 93 -
}
}
5. Độ phức tạp thuật toán
Ta có thể thấy là Độ phức tạp trong thuật toán Prim là O(n
2
).
V. Bài toán ghi các bài hát
1. Phát biểu bài toán
C øi hát, dung lượng h ặc
a = (a
, a , . . . , a ).
ó n ba o chiều dài phát được ghi trong mảng :
ø phát tuần tự.
=j i
i
k
a
11
; là dung lượng bài hát thứ .
Tìm b
∈ Σ sao cho D(b) = Min{ D(k) : k ∈ Σ }
Minh họa :
Với n = 3; a = (5,10, 3).
i 1 2 3 Số hiệu bài hát
1 2 n
- Tần suất phát là như nhau, tìm va
- Gọi
Σ là tập hợp các hoán vò trên tập {1, ,n}.
Với K = (k
, k , . . ., k ) , ta đặt :
1 2 n
∈ Σ
n
j
∑ ∑
=
KD )(
=
i
k
a
k
i
a[i] 5 10 3 Dung lượng
b
1
k
a
21
k
a
k
a +
321
k
a
k
a
k
a ++
D(b)
(1,2,3) 5 5+10 = 15 5+10+3 = 18 38
(1,3,2) 5 5+3 = 8 5+3+10 = 18 31
(2 5 10+5+3 = 18 43 ,1,3) 10 10+5 = 1
(2 10+3 = 13 10+3+5 = 18 41 ,3,1) 10
(3,1,2) 3 3+5 = 8 3+5+10 = 18 29
(3,2,1) 3 3+10 = 13 3+10+5 = 18 34
Ta có : D(b) = d((3,1,2)) = Min{ D(k) : k
∈ Σ }.
ột cách đơn giản để tìm lời giải trên là vét cạn các hoán vò, nhưng khi đó
xác đònh trước một trật tự và xử lý dữ liệu theo
. Thiết kế
M
chi phí thời gian là quá lớn. Ta sẽ
trật tự này.
2
1 2 n
= (k
1
, , ,
∈ };
Input : (a , a , . . ., a )
Output : Hoán vò b
k
n
)
min = D(b) = Min {D(K) : K
Σ
Trần Tuấn Minh Khoa Toán-Tin
Simpo PDF Merge and Split Unregistered Version -
Sưu tầm bởi:
www.daihoc.com.vn
Thiết kế và đánh giá thuật toán - 94 -
T nhận xét rằng D(b) đạt min nếu
j
T
a có
1
;
∑
=
=
j
i
i
k
a
∀∈jn1. . đạt min .
k
a
được chọn vào là giá trò nhỏ nhất của dãy
trường hợp này là các Tj được
chọn trong mỗi bước thêm vào
đó, lời giải tìm được sẽ là lời giải tối ưu. Thuật toán
:
≡
i] = i,∀i; min = 0;t = 0;
arc in(a,n,i); // a[j] = min{a[i], a[n]};
- [i]
↔ b[j]; // Đổi chỗ
-[i]
↔ a[j];
ập nhật lại g rò min;
t = t + a
min = min + t;
rn min;
hư tạp của th ät toán
Và T
j
đạt Min nếu trong mỗi bước i,
i
con còn lại của a .
Đònh hướng cho thuật toán tham lam trong
tính theo trật tự tăng dần của a, phần tử a
i
được
chính là min của {a
, ,a }. Khi
i n
tham lam có the
record_greedy(a
å mô tả như sau
,b,n)
* Khởi động b[
* for (i = 1
→ n)
- Chọn j = m
b
a
- C iá t
[i];
* retu
3. Độ p ùc ua
ật toán chọn min được sử dụng chính là chọn trực tiếp, Ta d
hức tạp của thuật toán trong các trường hợp là O(n
2
).
Thu ễ thấy độ
p
4. Cài đặt
int record_greedy(int a[max],int b[max],int n)
{
int
b[i] = i;
+)
; // Chính xác lại b tại mỗi bước
oicho(a[i],a[j]);
[
Chính xác dần min trong mỗi bước
n;
int i,t= 0,min = 0;
j,k,x;
for ( i = 1; i <= n; i++) // Khởi động b
for (i = 1;i <=n; i+
{
j = arcmin(a,n,i);
Doich(b[i],b[j])
D
t += a i];
min += t; //
}
return mi
}
Trần Tuấn Minh Khoa Toán-Tin
Simpo PDF Merge and Split Unregistered Version -
Sưu tầm bởi:
www.daihoc.com.vn
Thiết kế và đánh giá thuật toán - 95 -
V øi chiếc túi xácI. Ba toán h (Knapsack)
1. Phát biểu bài toán
Có n vật, mỗi vật i , i∈{1, ,n} được đặc trưng bởi trọng lượng w
i
(kg) và
hả năng mang m kg. Giả sử w
i
, v
i
, m ∈
,
áp vào ba lô sao cho ba lô thu được có giá trò nhất.
ủa n vật có thể biểu diễn bởi mảng :
w = ( w
1
, w
2
, . . , w
n
);
Và giá trò tương ứng của các vật :
v = ( v
1
, v
2
,. . .,v
n
);
[ ], với qui ước :
giá trò v
i
(US). Có một chiếc túi xách có k
N*
∀i ∈ {1, ,n}.
Hãy chọn vật xe
Các trọng lượng w
i
c
Các vật chọn được được lưu trử trong mảng ε
ε[i] = 1 ⇔ Vật i được chọn.
Bài toán trở thành :
⎪
⎩
=∀∈
ni
i
,1};1,0{
ε
⎪
⎪
=
i
1
2.
⎪
⎧
→
∑
v
n
ii
max
ε
⎪
⎨
≤
∑
=
mw
i
ii
1
ε
⎪
n
Thiết kế thuật toán
Thuật toán tham lam cho bài toán chọn vật có giá trò giảm dần (theo đơn
iá ).
utput
, n, m)
≡
g
Input
w = ( w
1
, w
2
, . . . ,w
n
); // Trọng lượng
v = ( v
1
, v
2
,. . .,v
n
); // Giá trò
m = Sức chứa chiếc ba lô.
O
ε[1 n] ; // Đánh dấu các vật được chọn
Vmax : Giá trò lớn nhất của ba lô.
Mô tả :
Knap_Greedy(w,v,Chon
* Khởi động b[i] = i,
∀i = n,1 ; //Lưu trử chỉ sô làm cho mảng đơn giá giảm
dần.
ε ∀
* Khởi động
[i] = 0, i = n,1 Khởi động Vmax = 0; ;
* Tính đơn giá :
i
v
i
w
i
d =
; }, ,1{ ni
∈
∀
* for (i = 1; i <= n && m > 0 ; i++)
{
- Chọn j = arcmax(d,n,i); // d[j] = Max{d[i], ,d[n]};
Trần Tuấn Minh Khoa Toán-Tin
Simpo PDF Merge and Split Unregistered Version -
Sưu tầm bởi:
www.daihoc.com.vn
Thiết kế và đánh giá thuật toán - 96 -
- b[i] ↔ b[j] ;
- // Cập nhật lại Vmax, Chon[ ], m;
if (m > w[b[i]])
{
Vmax += v[b[i]];
ε[b[i] = 1;
m -= w[b[i]];
}
- d[i]
↔ d[j] ;
}
* return max;
Minh họa :
Với n = 4; m = 17
i 1 2 3 4
w[i] 8 10 9 5
v[i] 8 12 10 4
Đơn giá d[i] 1 6/5 10/9 4/5
Vật chọn
theo thuật
to
x x Ttl : 15/17
Vmax = 16
án
ε[i]
Phương án
u
x x Ttl : 17
Vmax = 18 tối ư
3. Độ phức tạp của thuật toán
Thuật toán chọn Max được sử dụng chính là chọn trực tiếp, nên độ phức tạp
của thu
4. Cài đặt
ật toán trong các trường hợp là O(n
2
).
X_GREEDY(long w[],long v[],int C[],int n,long m)
ble d[max]; // Mang don gia
b[i] = i;
C[i] = 0;
j = arcmax(d,n,i);
dcn(b[i],b[j]); //Đổi chỗ
long MA
{
int i,j,k,b[max];
long Vmax = 0;
dou
for (i = 1; i <= n; i++)
{
d[i] = (double)w[i]/v[i];
}
for(i = 1; i <= n && m > 0; i++)
{
Trần Tuấn Minh Khoa Toán-Tin
Simpo PDF Merge and Split Unregistered Version -