Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 37 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
37
Dung lượng
281 KB
Nội dung
Mộtsốphươngphápthiếtkếthuật giải
Nội dung của chương này là mộtsố chiến lược thiếtkếthuậtgiải như chia để trị, vét
cạn, tham lam, quy hoạch động Mặc dù đó là các chiến lược tổng quát, tuy nhiên
mỗi phươngpháp chỉ áp dụng cho những lớp bài toán phù hợp. Nội dung của chương,
ngoài phần trình bày về các phươngpháp còn có những ví dụ cụ thể, cả thuậtgiải và
cài đặt, để người đọc có một cái nhìn chi tiết về việc từ thuật toán đến chương trình.
8.1. Chia để trị (Divide and Conquer)
Chia để trị là một tư tưởng rất phổ biến trong cuộc sống và được áp dụng rất hiệu quả
trong Tin học. Tư tưởng cơ bản của phươngpháp chia để trị là chia một bài toán
lớn, khó giải thành các bài toán tương tự, có kích thước nhỏ hơn và dễ giải hơn
sao cho ta có thể phối hợp kết quả của các bài toán con đó để có kết quả của bài toán
lớn.
Rất nhiều thuật toán ta gặp ở chương trước đều mang tư tưởng "chia để trị": thuật
toán sắp xếp nhanh Quick sort, thuật toán sắp xếp trộn Merge sort, thuật toán tìm
kiếm nhị phân,… Chúng ta sẽ nghiên cứu bài toán Tháp Hà nội, là một bài toán điển
hình được giải bằng phươngpháp chia để trị.
8.1.1. Bài toán Tháp Hà Nội
Có N đĩa có đường kính khác nhau được đặt chồng lên nhau theo thứ tự giảm dần của
đường kính tính từ dưới lên. Có ba vị trí có thể đặt các đĩa đánh số 1, 2, 3. Chồng đĩa
ban đầu được đặt ở vị trí 1:
1 2 3
Cần chuyển cả chồng đĩa từ vị trí 1 sang vị trí 2, theo những quy tắc sau:
• Khi di chuyển một đĩa, phải đặt nó vào một trong ba vị trí đã cho.
• Mỗi lần chỉ có thể chuyển một đĩa và phải là đĩa ở trên cùng.
• Tạimột vị trí, đĩa nào mới chuyển đến sẽ phải đặt lên trên cùng. Đĩa lớn hơn
không bao giờ được phép đặt lên trên đĩa nhỏ hơn (hay nói cách khác: một đĩa chỉ
được đặt trên mặt đất hoặc đặt trên một đĩa lớn hơn)
Bài toán này có nguồn gốc là một truyền thuyết của Ấn độ rằng có một nhóm cao
tăng Ấn độ giáo được giao trọng trách chuyển dần 64 đĩa vàng giữa 3 cọc kim cương
theo các điều kiện đã nói ở phần trên. Khi nào hoàn tất công việc, tức là khi chuyển
xong toàn bộ 64 đĩa từ vị trí ban đầu sang vị trí kết thúc thì cũng là thời điểm tận thế.
Chúng ta giải bài toán bằng cách chia bài toán chuyển N đĩa, từ vị trí 1 sang vị trí 2
thành ba bài toán đơn giản hơn như sau:
1. Chuyển N-1 đĩa trên cùng từ vị trí 1 sang vị trí 3, dùng vị trí 2 làm trung gian.
2. Chuyển đĩa thứ N từ vị trí 1 sang vị trí 2.
3. Chuyển N-1 đĩa từ vị trí 3 sang vị trí 2, dùng vị trí 1 làm trung gian.
Chú ý rằng bài toán 1 và 3 tương tự như bài toán ban đầu, chỉ khác là kích thước nhỏ
hơn. Chúng cũng sẽ được giải bằng phươngpháp “chia để trị” giống như bài toán ban
đầu. Dễ dàng kiểm tra là khi giải như vậy chúng vẫn thoả mãn các điều kiện. Bài toán
2 thì được giải rất đơn giản.
Thuật toán được viết dưới dạng giả mã như sau:
Procedure Hanoi;
begin
Move(n,1,2,3);
end;
Procedure Move(n,a,b,c);
{chuyển n đĩa, từ vị trí a sang vị trí b, dùng vị trí c làm trung gian }
begin
if n=0 then exit;
Move(n-1,a,c,b);
writeln('Chuyển đĩa ',n, ' từ vị trí ',a, 'sang vi tri ',b);
Move(n-1,c,b,a);
end;
Chúng ta hãy dừng lại một chút để phân tích độ phức tạp tính toán. Gọi T(n) là số
thao tác chuyển đĩa cần thiết để chuyển xong n đĩa. Theo thuật toán trên ta có:
T(n) = T(n-1) + 1 + T(n-1).
Bằng các phươngphápgiải công thức truy hồi ta có được T(n) = 2
n
-1. Áp dụng kết
quả này với giả thiết rằng mỗi cao tăng phải mất 1 giây để chuyển xong một đĩa từ
cọc này sang cọc kia, ta thấy thời gian để chuyển toàn bộ 64 đĩa vàng là T(64)=2
16
-
1=18446744073709551615 giây. Như vậy ngày tận thế (nếu có) theo truyền thuyết
phải 600 tỉ năm nữa mới đến.
Chúng ta sẽ phân tích mộtthuật toán nữa để thấy được sự hiệu quả của phươngpháp
chia để trị. Bài toán được chọn để phân tích tiếp theo là bài toán nhân 2 số lớn.
8.1.2. Bài toán nhân hai số lớn
Rất nhiều ứng dụng trong thực tế đòi hỏi phải xử lí các số rất lớn, nằm ngoài khoảng
biểu diễn của các kiểu cơ sở của ngôn ngữ lập trình (chẳng hạn việc tìm các số
nguyên tố rất lớn trong mã hoá RSA). Để giải quyết các yêu cầu đó, chúng ta phải
xây dựng các kiểu số rất lớn và xây dựng các phép toán tương ứng. Trong phần này ta
chỉ xét phép toán nhân đối với hai số rất lớn. Giả thiết cả hai đều có n chữ số và được
biểu diễn bằng mảng. Bài toán nhân 2 số lớn phát biểu như sau:
Input. A,B là 2 số nguyên có n chữ số: A=A
1
A
2
….A
n
và B=B
1
B
2
….B
n
.
Output. C=A.B
Thuật toán tự nhiên (brute-force) của bài toán nhân 2 số lớn là giảithuật nhân tay ta
vẫn thực hiện: lần lượt nhân từng chữ số của số thứ hai với số thứ nhất, dịch kết quả
theo vị trí và cộng các kết quả trung gian lại.
Chẳng hạn để nhân A=1981 và B=1234 ta tiến hành như sau:
1981
× 1234
7924
+ 5943
3962
1981
2444554
Thuật toán nhân 2 số lớn kiểu nhân tay được mô tả bằng giả mã:
function Mul(A,B,n)
begin
T := 0;
for i := 1 to n do begin
D := A* B
i
;
D := D shl (i-1); {dịch D sang trái i-1 chữ số, tức là nhân D với 10
i-1
}
T := T + D;
end;
return T;
end;
Dễ dàng tính được độ phức tạp tính toán của thuật toán này là O(n
2
). Chúng ta cố
gắng giảm bậc của thuật toán với tư tưởng chia để trị. Để đơn giản, ta giả thiết n=2k
và tách A,B dưới dạng XY và UV trong đó X,Y,U,V là các số có k chữ số. Như vậy
phép nhân 2 số A,B được tính như sau:
A.B = (X.10
k
+ Y).(U.10
k
+V) = XU.10
2k
+ (XV+YU).10
k
+UV.
Kết quả là bài toán nhân 2 số A.B có 2k chữ số được chia thành 4 bài toán con nhân
các số k chữ số và mộtsố phép cộng, trừ. Nhưng như vậy vẫn còn nhiều. Ta tiếp tục
cải tiến bằng nhận xét:
XV+YU = (X+U).(Y+V) - (XY + UV).
Đặt P = XY; Q = UV; R = (X+U).(Y+V). Từ 2 đẳng thức trên ta có:
A.B = P.10
2k
+ (R-P-Q).10
k
+Q.
Như vậy bài toán nhân 2 số A.B có n chữ số được chia thành 3 bài toán con nhân các
số n/2 chữ số và mộtsố phép cộng, trừ. Thuật toán được viết dạng giả mã như sau:
function Mul(A,B,n)
begin
if n=1 then return A
1
*B
1
;
k = n / 2;
X :=A(1 k); Y := A(k+1 n);
U :=B(1 k); V := B(k+1 n);
P := Mul(X,Y,k);
Q := Mul(X,Y,k);
R := Mul(X+U,Y+V,k);
T := P shl n + (R-P-Q) shl k + Q;
return T
end;
Để xác định độ phức tạp của thuật toán, ta coi là thao tác cơ bản là phép nhân, cộng
và dịch trái từng chữ số. Gọi T(n) là số thao tác cơ bản để thực hiện nhân 2 số có n
chữ số. Ta có:
T(n) = 3T(n/2) + C.n
Giải ra ta có T(n) = n
log
2
3
= n
1.59
, tức là có mộtsố cải thiện so với thuật toán nhân tay.
(Tuy nhiên khác biệt cũng không rõ rệt và chỉ thể hiện khi n khá lớn nên thông
thường trong các bài toán không lớn lắm người ta thường dùng thuật toán đầu tiên).
Qua các phần trên chúng ta đã thấy được phần nào hiệu quả của phươngpháp chia để
trị. Cuối chương này chúng ta sẽ gặp lại tư tưởng chia để trị trong phần nói về
phương pháp quy hoạch động. Quy hoạch động là tư tưởng chia để trị triệt để và là
một phươngpháp cực kì hiệu qủa trong việc giải các bài toán tối ưu.
8.2. Vét cạn (Exhausted search)
Vét cạn, duyệt, quay lui… là mộtsố tên gọi tuy không đồng nghĩa nhưng cùng chỉ
một phươngpháp rất đơn giản trong tin học: tìm nghiệm của một bài toán bằng
cách xem xét tất cả các phương án có thể. Đối với con người phươngpháp này
thường là không khả thi vì sốphương án cần kiểm tra quá lớn. Tuy nhiên đối với máy
tính, nhờ tốc độ xử lí nhanh, máy tính có thể giải rất nhiều bài toán bằng phương
pháp vét cạn.
Ưu điểm lớn nhất của phươngpháp vét cạn là luôn đảm bảo tìm ra nghiệm chính
xác. Ngoài ra phươngpháp vét cạn còn có mộtsố ưu điểm so với các phươngpháp
khác là đòi hỏi rất ít bộ nhớ và cài đặt đơn giản. Hạn chế duy nhất của phươngpháp
này là thời gian thực thi rất lớn, độ phức tạp thường ở bậc mũ. Do đó vét cạn
thường chỉ áp dụng tốt với các bài toán có kích thước nhỏ.
Mặc dù vậy, không nên coi thường phươngpháp này. Rất nhiều bài toán chỉ có thuật
toán duy nhất là vét cạn: từ bài toán đơn giản như tìm số lớn nhất trong một dãy số
đến các bài toán NPC. Trong mộtsố tình huống khác, chẳng hạn như thời gian lập
trình hạn chế thì vét cạn có thể coi như mộtgiảipháp tình thế. Rất nhiều trường hợp
ta có thể sử dụng vét cạn theo phương châm: thà mất 1h để viết một chương trình
vét cạn chạy trong trong 4 tiếng, còn hơn mất 4 ngày tìm thuật toán hiệu qủa để
chương trình chạy trong 1 phút.
Chúng ta không đề cập kĩ về việc áp dụng phươngpháp vét cạn đối với các bài toán
đơn giản như tìm giá trị nhỏ nhất, lớn nhất hay tìm tất cả các số nguyên tố của một
tập hợp. Chúng ta sẽ xem xét thuật toán vét cạn đối với các bài toán tìm cấu hình tổ
hợp và bài toán tối ưu tổ hợp, là lớp các bài toán rất tổng quát và phổ biến trong tin
học.
8.2.1. Bài toán tìm cấu hình tổ hợp
Có rất nhiều bài toán trong Tin học có yêu cầu dạng: tìm các đối tượng x thoả mãn
những điều kiện nhất định trong một tập S các đối tượng cho trước. Bài toán tìm cấu
hình tổ hợp là bài toán yêu cầu tìm các đối tượng x có dạng là một vector thoả mãn
các điều kiện sau:
1. Đối tượng x gồm n phần tử: x = (x
1
,x
2
,…x
n
).
2. Mỗi phần tử x
i
có thể nhận một trong các giá trị rời rạc a
1
, a
2
, … a
m
.
3. x thoả mãn các ràng buộc có thể cho bởi hàm logic G(x).
Tuỳ từng trường hợp mà bài toán có thể yêu cầu: tìm một nghiệm, tìm tất cả nghiệm
hoặc đếm số nghiệm.
Trước hết chúng ta nhắc lại mộtsố cấu hình tổ hợp cơ bản.
a) Tổ hợp
Một tổ hợp chập k của n là một tập con k phần tử của tập n phần tử.
Chẳng hạn tập {1,2,3,4} có các tổ hợp chập 2 là: {1,2}, {1,3, {1,4, {2,3}, {2,4},
{3,4}. Vì trong tập hợp các phần tử không phân biệt thứ tự nên tập {1,2} cũng là tập
{2,1} và do đó, ta coi chúng chỉ là một tổ hợp.
Bài toán đặt ra cho chúng ta là hãy xác định tất cả các tổ hợp châp k của tập n
phần tử. Để đơn giản ta chỉ xét bài toán tìm các tổ hợp của tập các số nguyên từ 1
đến n. Đối với một tập hữu hạn bất kì, bằng cách đánh số thứ tự của các phần tử, ta
cũng đưa được về bài toán đối với tập các số nguyên từ 1 đến n.
Nghiệm cần tìm của bài toán tìm các tổ hợp chập k của n phần tử phải thoả mãn các
điều kiện sau:
1. Là một vector x =(x
1
,x
2
,…x
k
)
2. x
i
lấy giá trị trong tập {1,2,…n}
3. Ràng buộc: x
i
<x
i+1
với mọi giá trị i từ 1 đến k-1.
Có ràng buộc 3 là vì tập hợp không phân biệt thứ tự phần tử nên ta sắp xếp các phần
tử theo thứ tự tăng dần.
b) Chỉnh hợp lặp
Chỉnh hợp lặp chập k của n là một dãy k thành phần, mỗi thành phần là một phần tử
của tập n phần tử, có xét đến thứ tự và không yêu cầu các thành phần khác nhau.
Một ví dụ dễ thấy nhất của chỉnh hợp lặp là các dãy nhị phân. Một dãy nhị phân độ
dài m là một chỉnh hợp lặp chập m của tập 2 phần tử {0,1}. Chẳng hạn 101 là một
dãy nhị phân độ dài 3. Ngoài ra ta còn có 7 dãy nhị phân độ dài 3 nữa là 000, 001,
010, 011, 100, 110, 111. Vì có xét thứ tự nên dãy 101 và dãy 011 là 2 dãy khác nhau.
Như vậy, bài toán xác định tất cả các chỉnh hợp lặp chập k của tập n phần tử yêu
cầu tìm các nghiệm như sau:
1. Là một vector x =(x
1
,x
2
,…x
k
)
2. x
i
lấy giá trị trong tập {1,2,…n}
3. Không có ràng buộc nào giữa các thành phần.
Chú ý là cũng như bài toán tìm tổ hợp, ta chỉ xét đối với tập n số nguyên từ 1 đến n.
Nếu tập hợp cần tìm chỉnh hợp không phải là tập các số nguyên từ 1 đến n thì ta có
thể đánh số các phần tử của tập đó để đưa về tập các số nguyên từ 1 đến n
c) Chỉnh hợp không lặp
Khác với chỉnh hợp lặp là các thành phần được phép lặp lại, tức là có thể giống nhau,
chỉnh hợp không lặp chập k của tập n phần tử cũng là một dãy k thành phần lấy từ tập
n phần tử có xét thứ tự nhưng các thành phần không được phép giống nhau.
Chẳng hạn có n người, một cách chọn ra k người để xếp thành một hàng là một chỉnh
hợp không lặp chập k của n.
Một trường hợp đặc biệt của chỉnh hợp không lặp là hoán vị. Hoán vị của một tập n
phần tử là một chỉnh hợp không lặp chập n. Nói một cách trực quan thì hoán vị của
tập n phần tử là phép thay đổi vị trí của các phần tử (do đó mới gọi là hoán vị).
Nghiệm của bài toán tìm các chỉnh hợp không lặp chập k của tập n số nguyên từ
1 đến n là các vector x thoả mãn các điều kiện:
1. x có k thành phần: x = (x
1
,x
2
,…xk)
2. Các giá trị xi lấy trong tập {1,2, n}
3. Ràng buộc: các giá trị xi đôi một khác nhau, tức là xi≠xj với mọi i≠j.
Đó là mộtsố bài toán tìm cấu hình tổ hợp cơ bản. Chúng ta sẽ xem xét mộtsố bài
toán khác để thấy tính phổ biến của lớp các bài toán dạng này.
d) Bài toán xếp hậu
Cho bàn cờ vua nxn. Hãy xếp n con hậu lên bàn cờ sao cho không con nào khống chế
con nào. Hai 2 con hậu khống chế nhau nếu chúng ở trên cùng một hàng, một cột
hoặc một đường chéo.
Chẳng hạn ta có một cách đặt sau, các ô đen là các vị trí đặt hậu:
Để chuyển bài toán này về dạng chuẩn của bài toán tìm cấu hình tổ hợp, ta có có nhận
xét: mỗi con hậu phải ở trên một hàng và một cột. Do đó ta coi con hậu thứ i ở hàng i
và nếu biết x[i] là cột đặt con hậu thứ i thì ta suy ra được lời giải. Vậy nghiệm của bài
toán có thể coi là một vector x gồm n thành phần với ý nghĩa:
1. Con hậu thứ i được đặt ở hàng i và cột x[i].
2. x[i] lấy giá trị trong tập {1,2…n}
3. Ràng buộc: các giá trị x[i] khác nhau từng đôi một và không có 2 con hậu ở
trên cùng một đường chéo.
Trong phần cài đặt, chúng ta sẽ phân tích chi tiết về các ràng buộc trên.
e) Bài toán từ đẹp (xâu ABC)
Một từ đẹp là một xâu độ dài n chỉ gồm các kí tự A,B,C mà không có 2 xâu con liên
tiếp nào giống nhau. Chẳng hạn ABAC là một từ đẹp độ dài 4, BABCA là một từ đẹp
độ dài 5.
Bài toán tìm tất cả các từ đẹp độ dài n cho trước yêu cầu tìm nghiệm là các vector x
có n thành phần:
1. xi nhận giá trị trong tập {A,B,C}
2. x không có 2 đoạn con liên tiếp nào bằng nhau.
Trước khi trình bày về phươngpháp vét cạn giải các bài toán tìm cấu hình tổ hợp,
chúng ta xem xét các bài toán tối ưu tổ hợp, vì các bài toán tối ưu tổ hợp thực chất là
sự mở rộng của bài toán tìm cấu hình tổ hợp.
8.2.2. Bài toán tối ưu tổ hợp
Bài toán tối ưu tổng quát có thể phát biểu như sau: Cho tập B khác rỗng và một hàm
f:B→R gọi là hàm mục tiêu. Cần tìm phần tử x thuộc B sao cho f(x) đạt giá trị nhỏ
nhất hoặc lớn nhất. Phần tử x là nghiệm của bài toán còn được gọi là phương án tối
ưu.
Bài toán tối ưu tổ hợp là bài toán tìm phương án tối ưu trên tập các cấu hình tổ hợp.
Nghiệm của bài toán cũng là một vector x gồm n thành phần sao cho:
1. x = (x
1
,x
2
,…xn)
2. xi lấy giá trị trong tập {a
1
,a
2
,…am}
3. x thoả mãn các ràng buộc cho bởi hàm G(x).
4. f(x) → min/max.
Chúng ta sẽ phân tích mộtsố bài toán tối ưu tổ hợp điển hình. Phần lớn đều là các bài
toán NPC.
a) Bài toán xếp balô
Có một balô có tải trọng m và n đồ vật, đồ vật i có trọng lượng wi và có giá trị vi.
Hãy lựa chọn các vật để cho vào balô sao cho tổng trọng lượng của chúng không quá
M và tổng giá trị của chúng là lớn nhất.
Mỗi cách chọn các đồ vật cho vào balô đều tương ứng với một vector x gồm n thành
phần mà xi=1 nếu chọn đưa vật thứ i vào balô, và xi=0 nếu vật thứ i không được
chọn.
Khi đó ràng buộc tổng trọng lượng các đồ vật không quá tải trọng của balô được viết
thành:
mwx
n
1i
ii
≤
∑
=
Hàm mục tiêu là tổng giá trị của các đồ vật được chọn:
maxvx)x(f
n
1i
ii
→=
∑
=
Nghiệm của bài toán cũng là một vector x gồm n thành phần sao cho:
1. x = (x
1
,x
2
,…xn)
2. xi lấy giá trị trong tập {0,1}
3. Ràng buộc:
mwx
n
1i
ii
≤
∑
=
4.
maxvx)x(f
n
1i
ii
→=
∑
=
.
b) Bài toán người du lịch
Có n thành phố, d[i,j] là chi phí để di chuyển từ thành phố i đến thành phố j. (Nếu
không có đường đi thì d[i,j] = ∞). Một người muốn đi du lịch qua tất cả các thành
phố, mỗi thành phố một lần rồi trở về nơi xuất phát sao cho tổng chi phí là nhỏ nhất.
Hãy xác định một đường đi như vậy.
Phương án tối ưu của bài toán cũng là một vector x, trong đó xi là thành phố sẽ đến
thăm tại lần di chuyển thứ i. Các điều kiện của x như sau:
1. x = (x
1
,x
2
,…xn)
2. xi lấy giá trị trong tập {1,2,…n}
3. Ràng buộc: xi ≠ xj với mọi i≠j và d[xi,xi
+1
]<∞ với mọi i=1,2, n, coi xn
+1
=x
1
.
4. f(x) =
min]x,x[d
n
1i
1ii
→
∑
=
+
Trên đây ta đã xét mộtsố bài toán tìm cấu hình tổ hợp và bài toán tối ưu tổ hợp.
Trong phần tiếp chúng ta sẽ tìm hiểu phươngpháp vét cạn giải các bài toán đó.
8.2.3. Phươngpháp vét cạn giải các bài toán cấu hình tổ hợp và tối ưu tổ hợp
Phương pháp vét cạn là phươngpháp rất tổng quát để đơn giản để giải các bài toán
cấu hình tổ hợp và tối ưu tổ hợp. ý tưởng cơ bản là: bằng một cách nào đó sinh ra tất
cả các cấu hình có thể rồi phân tích các cấu hình bằng các hàm ràng buộc và hàm
mục tiêu để tìm phương án tối ưu (do đó phươngpháp này còn được gọi là duyệt toàn
bộ).
Dựa trên ý tưởng cơ bản đó, người ta có 3 cách tiếp cận khác nhau để duyệt toàn bộ
các phương án.
Phương pháp thứ nhất là phươngpháp sinh tuần tự. Phươngpháp này cần xác định
một quan hệ thứ tự trên các cấu hình (gọi là thứ tự từ điển) và một phép biến đổi để
biến một cấu hình thành cấu hình ngay sau nó. Mỗi lần sinh được một cấu hình thì
tiến hành định giá, so sánh với cấu hình tốt nhất đang có và cập nhật nếu cấu hình
mới tốt hơn.
Giả mã của thuật toán tìm cấu hình tối ưu bằng phươngpháp sinh như sau:
Procedure Generate;
begin
x := FirstConfig;
best := x;
Repeat
x := GenNext(x);
if f(x) "tốt hơn" f(best) then best := x;
Until x = LastConfig;
end;
Thuật toán thực hiện như sau: tìm cấu hình đầu tiên và coi đó là cấu hình tốt nhất.
Sau đó lần lượt sinh các cấu hình tiếp theo, mỗi lần sinh được một cấu hình ta so sánh
nó với cấu hình tốt nhất hiện có (best) và nếu nó tốt hơn thì cập nhật best. Quá trình
dừng lại khi ta sinh được cấu hình cuối cùng. Kết quả ta được phương án tối ưu là
best.
Phương pháp sinh tuần tự thường rất khó áp dụng. Khó khăn chủ yếu là do việc xác
định thứ tự từ điển, cấu hình đầu tiên, cấu hình cuối cùng và phép biến đổi một cấu
hình thành cấu hình tiếp theo thường là không dễ dàng.
Phương pháp thứ hai là phươngpháp thử sai − quay lui (Backtracking). Tư tưởng cơ
bản của phươngpháp là xây dựng từng thành phần của cấu hình, tại mỗi bước xây
dựng đều kiểm tra các ràng buộc và chỉ tiếp tục xây dựng các thành phần tiếp theo
nếu các thành phần hiện tại là thoả mãn. Nếu không còn phương án nào để xây dựng
thành phần hiện tại thì quay lại, xây dựng lại các thành phần trước đó.
Giả mã của thuật toán quay lui như sau.
procedure Backtrack;
begin
i := 1; x[1] := a0;
repeat
x[i] := next(x[i]);
if ok then Forward else Backward;
until i=0;
end;
procedure Forward;
[...]... bộ nhớ Phươngpháp tham lam xây dựng các thuật toán giải các bài toán tối ưu dựa trên tư tưởng tối ưu cục bộ theo một chiến lược tư duy kiểu con người, nhằm nhanh chóng đạt đến một lời giải "tốt" Có mộtsốthuật toán dựa trên tư tưởng của phươngpháp tham lam thực sự tìm được phương án tối ưu (chẳng hạn thuật toán Kruscal tìm cây khung cực tiểu), còn lại đa số các thuật toán dựa trên phươngpháp tham... đến phương án tối ưu Giảipháp thứ 2 là sử dụng các phươngpháp khác, mà hai phươngpháp nổi bật nhất là phươngpháp quy hoạch động và phươngpháp tham lam Phần tiếp theo, chúng tôi sẽ trình bày sơ lược về kỹ thuật nhánh cận 8.2.4 Kỹ thuật nhánh cận Nguyên nhân dẫn đến độ phức tạp của các bài toán tối ưu tổ hợp là hiện tượng bùng nổ tổ hợp Đó là hiện tượng số cấu hình tổ hợp tăng theo hàm mũ đối với số. .. tổ hợp cũng có thể giảimột cách tương đối hiệu quả bằng phươngpháp quy hoạch động Chúng ta sẽ xem xét mộtsố bài toán a) Bài toán phân tích số Cho số tự nhiên n Hãy cho biết có bao nhiêu cách phân tích số n thành tổng các số nguyên dương Các cách phân tích không xét thứ tự, chẳng hạn 6=1+5=5+1 được coi là một cách n=0 cũng được coi là 1 cách phân tích Để giải bài toán bằng phươngpháp quy hoạch động,... Nhìn chung phươngpháp quay lui làm giảm đáng kể những khó khăn của phươngpháp sinh (không cần tìm thứ tự từ điển và nhất là không cần tìm quy tắc sinh cấu hình tiếp theo) Tuy nhiên, trong mộtsố bài toán mà cần đánh dấu trạng thái, phươngpháp quay lui không đệ quy được trình bày ở trên phải xử lí phức tạp hơn nhiều so với phươngpháp quay lui đệ quy Phươngpháp quay lui đệ quy là phươngpháp đơn giản... kĩ thuật mạnh nhưng muốn để áp dụng tốt đòi hỏi những phân tích rất chi tiết Hơn nữa nhiều trường hợp có đặt cận thì sốphương án cần duyệt vẫn quá nhiều Trong những trường hợp như vậy chúng ta cần phải có những cách tiếp cận khác Phần tiếp theo trình bày về một phươngpháp cực kì hiệu quả, đó là phươngpháp quy hoạch động 8.3 Phươngpháp quy hoạch động (Dymnamic plan) Quy hoạch động là một phương pháp. .. phươngpháp quy hoạch động Tuy nhiên không có phươngpháp nào là hoàn hảo Phươngpháp quy hoạch động có mộtsố nhược điểm lớn như sau: 1 Không phải bài toán nào cũng giải được bằng quy hoạch động Hiện nay người ta vẫn chưa tìm được điều kiện cần và đủ để một bài toán có thể giải được bằng phươngpháp quy hoạch động Do đó để xác định được một bài toán có thể giải được bằng quy hoạch động và tìm được công... nhiều giảithuật tham lam khác nhau giải bài toán này Chúng tôi xin trình bày mộtgiảithuật theo chiến lược chọn cái tốt trước và mộtgiảithuật theo chiến lược cải tiến cái hiện có Giảithuật theo chiến lược chọn cái tốt nhất trước có ý tưởng rất đơn giản: tại mỗi bước ta sẽ chọn thành phố tiếp theo là thành phố chưa đến thăm mà chi phí từ thành phố hiện tại đến thành phố đó là thấp nhất Giải thuật. .. quát chỉ có thuật toán tối ưu duy nhất là vét cạn Tuy nhiên, nhược điểm của phương pháp vét cạn là độ phức tạp tính toán rất lớn do hiện tượng bùng nổ tổ hợp Các bạn nhớ lại rằng số hoán vị của tập n phần tử là n! Do đó trong trường hợp xấu nhất thuật toán vét cạn đối với bài toán người du lịch là O(n!) Có 2 giảipháp khắc phục vấn đề này Giảipháp thứ nhất cải tiến phương pháp vét cạn bằng kỹ thuật nhánh... nào để tìm lại kết quả? Có 2 phương án Phương pháp thứ nhất là dựa vào bảng phương án Phươngpháp thứ hai là xây dựng bảng truy vết Dựa trên bảng phương án ta sẽ tìm được phần tử có L[i] lớn nhất Đó chính là phần tử cuối cùng của dãy kết quả Phần tử đứng ngay trước nó sẽ là phần tử j mà aj . Một số phương pháp thiết kế thuật giải
Nội dung của chương này là một số chiến lược thiết kế thuật giải như chia để trị, vét. phương án tối ưu. Giải pháp thứ 2 là sử dụng các phương pháp khác, mà hai
phương pháp nổi bật nhất là phương pháp quy hoạch động và phương pháp tham lam.
Phần