Mở đầu là thuật toán QUAY LUI
Trước hết, mình sẽ trích lại lý thuyết cho thuật toán này (trích trong "Bài giảng chuyên đề" của LÊ MINH HOÀNG)
Thuật toán quay lui dùng để giải bài toán liệt kê các cấu hình. Mỗi cấu hình được xây dựng bằng cách xây dựng từng phần tử, mỗi phần tử được chọn bằng cách thử tất cả các khả năng.
Giả thiết cấu hình cần liệt kê có dạng (x1, x2, ..., xN). Khi đó thuật toán quay lui thực hiện qua các bước sau:
1) Xét tất cả các giá trị x1 có thể nhận, thử cho x1 nhận lần lượt các giá trị đó. Với mỗi giá trị thử gán cho x1 ta sẽ:
2) Xét tất cả các giá trị x2 có thể nhận, lại thử cho x2 nhận lần lượt các giá trị đó. Với mỗi giá trị thử gán cho x2 lại xét tiếp các khả năng chọn x3... cứ tiếp tục như vậy đến bước:
N) Xét tất cả các giá trị xN có thể nhận, thử cho xN nhận lần lượt các giá trị đó, thông báo cấu hình tìm được (x1, x2, ..., xN).
Trên phương diện quy nạp, có thể nói rằng thuật toán quay lui liệt kê các cấu hình N phần tử dạng (x1, x2, ..., xN) bằng cách thử cho x1 nhận lần lượt các giá trị có thể. Với mỗi giá trị thử gán cho x1 lại liệt kê tiếp cấu hình (N - 1) phần tử (x2, x3, ..., xN).
Mô hình của thuật toán quay lui có thể mô tả như sau:
Code:
{Thủ tục này thử cho xi nhận lần lượt các giá trị mà nó có thể nhận}
Procedure Try(i: Integer);
Begin
For (mọi giá trị V có thể gán cho xi) Do
Begin
<Thử cho xi := V>;
If (xi là phần tử cuối cùng trong cấu hình) Then
<Thông báo cấu hình tìm được>
Else
Begin
<Ghi nhận việc cho xi nhận giá trị V (nếu cần)>;
Try(i + 1); {Gọi đệ quy để chọn tiếp x(i+1)}
<Nếu cần, bỏ ghi nhận việc thử xi := V, để thử giá trị khác>;
End;
End;
End;
Thuật toán quay lui sẽ bắt đầu bằng lời gọi Try(1)
Ta có thể trình bày quá trình tìm kiếm lời giải của thuật toán quay lui bằng cây sau:
Code:
Try(1)
/ \
Try(2) Try(2)
/ \ / \
Try(3) Try(3) Try(3) Try(3)
/ \ / \ / \ / \
(--) (--) (--) (--) (--) (--) (--) (--)
Cây tìm kiếm quay lui
Bookmarks