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

quay lui de chuong trinh

97 404 1

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

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 97
Dung lượng 272,5 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Phương pháp thuật toán quay lui Backtracking Trong các kỹ thuật cơ bản để thiết kế thuật toán, quay lui là một trong những kỹ thuật quan trọng nhất vì nó cho phép giải một lớp các bài

Trang 1

THUẬT TOÁN QUAY LUI (BACKTRACKING)

1 Phương pháp (thuật toán quay lui Backtracking)

Trong các kỹ thuật cơ bản để thiết kế thuật toán, quay lui

là một trong những kỹ thuật quan trọng nhất vì nó cho phép giải một lớp các bài toán khá lớn có dạng tổng quát như sau: Tìm một (hoặc tất cả) bộ nghiệm (x1, x2, , xn) thỏa mãn điều kiện F nào đó, trong đó các thành phần xi được chọn từ một tập hữu hạn Di với mọi i = 1, 2, , n.

Tư tưởng của phương pháp quay lui như sau :

- Ta xây dựng bộ nghiệm từng bước, bắt đầu từ thành phần nghiệm x1 được chọn trong các giá trị có thể S1 = D1.

- Giả sử đã chọn được các thành phần x1, x2, , xi-1, từ các điều kiện của bài toán ta sẽ xác định được tập Si gồm các giá trị được chọn cho thành phần nghiệm xi Tập Si là tập con của Di và phụ thuộc vào các thành phần x1, x2, , xi-1 đã chọn Chọn một phần tử xi thuộc Si như một thành phần của

Trang 2

bộ nghiệm Từ bộ (x1, x2, , xi) lặp lại quá trình trên để tiếp tục mở rộng nghiệm cho thành phần xi+1 Nếu không chọn được thành phần nào của xi+1 (do Si+1 rỗng) thì ta quay lại chọn một phần tử khác của Si làm thành phần nghiệm xi (ý nghĩa của quay lui là ở bước này).

- Trong quá trình mở rộng nghiệm ta luôn kiểm tra nghiệm thành phần có phải là nghiệm của bài toán hay không Nếu chỉ cần một nghiệm thì ta dừng lại, nếu cần tìm tất cả các nghiệm thì quá trình tìm nghiệm chỉ dừng khi tất

cả các khả năng chọn các thành phần nghiệm đã vét cạn Quay lui là một trong các phương pháp vét cạn trong đó các giá trị nghiệm được chọn không thực hiện được bằng

Trang 3

việc xây dựng các tập giá trị có thể Si khi tìm thành phần nghiệm xi và quay lui khi không mở rộng thành phần nghiệm xi+1.

Tuy nhiên hạn chế của phương pháp này là phải duyệt qua nhiều khả năng nên độ phức tạp của chương trình thường ở mức giai thừa hay hàm mũ nên tốc độ tính toán khá lâu trong trường hợp kích thước của dữ liệu vào khá lớn

Để khắc phục hạn chế này người ta tìm cách hạn chế các khả năng không đưa đến kết quả bằng phương pháp nhánh cận, tuy nhiên lớp bài toán dùng được phương pháp này không nhiều.

Đa số các bài toán vét cạn sử dụng phương pháp duyệt

đệ quy để xét hết mọi khả năng có thể có nghiệm theo nguyên tắc "thử sai" và quay lui Về tư tưởng, các thuật toán vét cạn rất đơn giản nhưng ứng dụng vào việc giải các bài toán cần có những kỹ thuật nhất định.

Để giải bài toán bằng thuật toán quay lui cần thực hiện

các công việc quan trọng sau:

* Tìm cách biểu diễn nghiệm của bài toán dưới dạng một dãy các đối tượng được chọn dần từng bước (x1, x2, , xn).

Trang 4

* Xác định được tập Si các khả năng được chọn làm thành phần thứ i của nghiệm Chọn cách thích hợp để biểu diễn Si.

* Tìm các điều kiện để các nghiệm đã chọn là các nghiệm của bài toán.

Một số lưu ý khi xây dựng thuật toán quay lui:

* Phải duyệt qua mọi phương án của bài toán có thể chứa nghiệm (vét cạn).

* Tránh trường hợp duyệt trùng lặp các khả năng đã duyệt.

Để giải các bài toán bằng thuật toán quay lui, thông thường ta thường dùng thủ tục đệ quy Try(i : Integer) để chọn thành phần nghiệm xi

Có ba dạng cơ bản trong các thuật toán quay lui:

Dạng 1: Tìm tất cả các nghiệm.

Dạng 2: Tìm một nghiệm.

Trang 5

Ta lần lượt xét cách giải các dạng trên bằng phương pháp quay lui:

Trang 6

2 Dạng 1: Tìm tất cả các nghiệm

Trang 10

Mô hình của thuật toán quay lui có thể mô tả như sau:

Trang 11

Procedure Try(i: Integer); {Thủ tục này thử cho x i nhận lần lượt các giá trị mà nó có thể nhận}

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>

Trang 12

Try(i + 1); {Gọi đệ quy để chọn tiếp xi+1}

VÍ DỤ 1 LIỆT KÊ DÃY NHỊ PHÂN ĐỘ DÀI N

Input: file văn bản NHIPHAN.INP chứa số nguyên dương N

(N<=30).

Trang 14

Ý tưởng:

Biểu diễn dãy nhị phân độ dài N dưới dạng (x1, x2, , xn) Ta sẽ liệt kê các dãy này bằng cách thử dùng các giá trị {0, 1} gán cho xi Với mỗi giá trị thử gán cho xi lại thử các giá trị có thể gán cho xi+1… Chương trình liệt kê bằng thuật toán quay lui có thể viết:

VÍ DỤ 2 TỔ HỢP (XÁC ĐỊNH TỔ HỢP CHẬP K CỦA TẬP

N PHẦN TỬ)

Input: file văn bản TOHOP.INP chứa hai số nguyên dương

n, k (1 ≤ k ≤ n ≤ 20 ) cách nhau ít nhất một dấu cách.

Output: file văn bản TOHOP.OUT ghi các tổ hợp chập k của

tập {1, 2, , n}

Trang 15

TOHOP.INP TOHOP.OUT

5 3 {1,2,3}

{1,2,4} {1,2,5} {1,3,4} {1,3,5} {1,4,5} {2,3,4} {2,3,5}

Trang 17

thoả mãn các điều kiện sau:

- Là một vectơ X= (x1, x2,…, xk);

- Xi lấy giá trị trong tập {1,2,3,…,n};

- Ràng buộc: xi < xi+1 với mọi giá trị i từ 1 đến k-1 (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).

Ta có: 1 ≤ x1 < x2<…< xk ≤ n, do đó xi được chọn là xi-1 + 1

≤ xi ≤ n - k + i (1 ≤ i ≤ k) ở đây ta giả thiết có thêm một số x0

= 0 khi xét i = 1 Như vậy ta sẽ xét tất cả các cách chọn x1 từ

1 (= x0 + 1) đến n - k + 1, với mỗi giá trị đó, xét tiếp tất cả các cách chọn x2 từ x1 + 1 đến n - k + 2, cứ như vậy khi chọn được đến xk thì ta có một cấu hình cần liệt kê

VÍ DỤ 3 LIỆT KÊ CÁC CHỈNH HỢP KHÔNG LẶP CHẬP K

Input: file văn bản CHINHHOP.INP chứa hai số nguyên

dương n, k (1 ≤ k ≤ n ≤ 20) cách nhau ít nhất một dấu cách.

Output: file văn bản CHINHHOP.OUT ghi các chỉnh hợp

Trang 19

xk ), ở đây các xi ∈ S và khác nhau đôi một.

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à vectơ X thoả mãn điều kiện:

- Là một vectơ X = (x1, x2,…, xk);

- Xi lấy giá trị trong tập {1,2,3,…,n};

- 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.

Như vậy thủ tục Try(i) - xét tất cả các khả năng chọn xi

- sẽ thử hết các giá trị từ 1 đến n, mà các giá trị này chưa

bị các phần tử đứng trước chọn Muốn xem các giá trị nào chưa được chọn ta sử dụng kỹ thuật dùng mảng đánh dấu:

- Khởi tạo một mảng c1, c2, , cn kiểu logic Ở đây ci cho biết giá trị i có còn tự do hay đã bị chọn rồi Ban đầu khởi tạo tất cả các phần tử mảng c là TRUE có nghĩa là các phần tử từ 1 đến n đều tự do.

VÍ DỤ 4 BÀI TOÁN PHÂN TÍCH SỐ

Trang 20

Hãy tìm tất cả các cách phân tích số n thành tổng của các số nguyên dương, các cách phân tích là hoán vị của nhau chỉ tính là 1 cách.

Input: file văn bản PHANTICH.INP chứa số nguyên dương n

Trang 21

Ý tưởng:

Ta sẽ lưu nghiệm trong mảng x, ngoài ra có một mảng

t Mảng t xây dựng như sau: ti sẽ là tổng các phần tử trong mảng x từ x1 đến xi: ti := x1 + x2 + + xi.

Khi liệt kê các dãy x có tổng các phần tử đúng bằng n,

để tránh sự trùng lặp ta đưa thêm ràng buộc xi-1 ≤ xi Khi ti

- Cuối cùng xét giá trị xi = n - ti-1 và in kết quả từ x1 đến xi.

VÍ DỤ 5 Trò chơi trên băng giấy (Hội thi GV Giỏi Hà Tĩnh 2012)

Trên một băng giấy người ta kẻ N ô vuông liên tiếp nhau theo chiều ngang Các ô vuông được đánh số từ 1 đến N theo chiều từ trái sang phải (1<N<50) Tại ô vuông số 1 có đặt một quân cờ Một nước đi trong trò chơi là dịch chuyển quân cờ về phía bên phải 1 hoặc 2 ô vuông.

Trang 22

Hãy đếm và liệt kê tất cả các cách dịch chuyển quân cờ từ ô vuông số 1 tới ô vuông N (Ký hiệu: ký hiệu ‘O’ mô tả dịch chuyển quân cờ về phía bên phải 1

ô vuông, ký hiệu ‘T’ mô tả dịch chuyển quân cờ về phía bên phải 2 ô vuông).

Dữ liệu vào là tệp văn bản BANG.INP ghi số nguyên dương N.

Dữ liệu ra là tệp văn bản BANG.OUT có cấu trúc:

- Dòng thứ nhất ghi số nguyên M là số cách dịch chuyển quân cờ từ ô vuông 1 đến ô vuông N.

- M dòng tiếp theo mỗi dòng ghi một cách dịch chuyển trong số M cách di chuyển quân cờ từ ô số 1 tới ô số N.

BANG.INP BANG.OUT

OOO OT TO

*

Trang 23

Input: file văn bản QUEENS.INP chứa số nguyên dương n

12.

Output: file văn bản QUEENS.OUT, mỗi dòng ghi một cách

Trang 25

Ví dụ một cách xếp với n = 5

Rõ ràng n quân hậu sẽ được đặt mỗi con một hàng

vì hậu ăn được ngang, ta gọi quân hậu sẽ đặt ở hàng 1 là quân hậu 1, quân hậu ở hàng 2 là quân hậu 2 quân hậu

ở hàng n là quân hậu n Vậy một nghiệm của bài toán sẽ

được biết khi ta tìm ra được vị trí cột của những quân hậu.

- Mảng b[2 2n] để đánh dấu một đường chéo.

- Mảng c[1 - n n – 1] để đánh dấu đường chéo còn lại.

Trang 26

- Ban đầu cả 3 mảng đánh dấu đều mang giá trị TRUE (Các cột và đường chéo đều tự do), nếu phần tử nào được chọn thì cả 3 đường chéo nhận giá trị bằng FALSE.

* Khi chọn vị trí cột j cho quân hậu thứ i, thì ta phải chọn ô (i, j) không bị các quân hậu đặt trước đó ăn, tức là phải chọn cột j còn tự do Điều này có thể kiểm tra (aj = bi+j = ci-j = TRUE).

cả các kết quả có thể có mà máy sinh ra

Trang 27

INPUT: Dữ liệu vào đọc từ file văn bản XOSO.INP gồm:

- Dòng đầu ghi các số N, M, K

- Dòng thứ i trong N dòng tiếp ghi thẻ chơi của

người i gồm K+1 số: K số đầu là các số hiệu của các ô chọn, cuối cùng là điểm tương ứng

OUPUT: Ghi kết quả ra file văn bản XOSO.OUT, mỗi dòng là

một kết quả gồm K số ghi số hiệu các ô mà máy đã sinh

Trang 28

Ý tưởng:

Ta nhận thấy rằng mỗi nghiệm của bài toán chính là một cấu hình của tổ hợp chập K của M phần tử Ta áp dụng thuật toán quay lui để duyệt mọi cấu hình tổ hợp để tìm ra cấu hình thoả mãn Tuy nhiên để giảm bớt số lần duyệt ta cần phải loại những thẻ mà chúng có tổng điểm bằng 0 và cần đánh dấu những thẻ đã được chọn Dùng mảng kt[0 51] of Boolean để phân biệt giữa ô có điểm và những ô không có điểm

Nếu kt[i]= False thì cho biết thẻ thứ i không có điểm Còn logic[i,j] = True cho ta biết người thứ i đánh dấu vào thứ j của thẻ

Trang 30

<Thông báo cấu hình tìm được>

Halt; {thoát khỏi chương trình}

End Else

Begin

Trang 31

Try(i + 1); {Gọi đệ quy để chọn tiếp x i+1 }

+ Điều kiện cần để một khả năng được chấp nhận ở bước thứ i là bước i+1 cũng có khả năng chấp nhận một nghiệm của nó và bước thứ i chưa phải bước cuối cùng Vì vậy có thể nhanh chóng tới đích nếu đưa ra qui luật chọn nghiệm của bước thứ i như sau :

Ở bước thứ i ta sẽ chọn nghiệm nào mà theo nó đưa ta tới bước i+1 có ít khả năng chấp nhận nhất (nghĩa là bước thứ i+1 vẫn có khả năng chọn nghiệm của nó, nhưng số nghiệm ít).

Trang 32

+ Một cách khác: Khi chấp nhận một khả năng chọn nghiệm cho bước thứ i, có thể sẽ tác động tới trạng thái bài toán Vì vậy ta tính toán trước nếu chọn nghiệm này thì trạng thái bài toán có thay đổi quá mức giới hạn cho phép hay không? Nghĩa là có vượt qua cận trên hoặc cận dưới của bài toán hay không ? Nếu vượt qua thì ta không chọn nghiệm ấy Trong nhiều bài toán những cận này cũng thu hẹp dần theo từng bước, nếu ta tìm được sự thay đổi của cận theo từng bước thì các khả năng chọn nghiệm ngày càng hẹp dần, bài toán nhanh chóng kết thúc.

Một khó khăn khác của loại toán hiện 1 nghiệm là: trường hợp bài toán vô nghiệm cần viết chương trình như thế nào? Phải duyệt hết mọi khả năng mới rõ kết luận vô nghiệm hay không vô nghiệm Nghĩa là đã đi theo mọi nhánh nhưng nhánh nào cũng đều không tới đích, do đó theo quy luật cứ quay lui mãi để tìm kiếm thì đến lúc nào đó dẫn đến tình trạng phải trở về ô xuất phát Vậy khi gặp ô chọn nghiệm mới trùng với ô xuất phát thì bài toán vô nghiệm Vậy trong thủ tục Try(i) ta thêm một bước kiểm tra xem chương trình có nghiệm hay không nữa

Trang 33

Một máy ATM hiện có n (n ≤ 20) tờ tiền có mệnh giá t1, t2, t3,…., tn Hãy đưa ra cách trả tiền đúng bằng s.

Input: Tệp ATM.INP có dạng:

- Dòng đầu là hai số n và s.

- Dòng thứ hai gồm n số t1, t2, t3,…., tn

Output: Tệp ATM.OUT có dạng: Nếu có thể trả đúng s thì

đưa ra cách trả, nếu không ghi -1.

Ý tưởng:

Nghiệm của bài toán là một dãy nhị phân độ dài n, trong đó thành phần thứ i bằng 1 nếu tờ tiền thứ i được sử dụng để trả, bằng 0 trong trường hợp ngược lại.

X= (x1, x2, , xn) là nghiệm nếu: x t1× + × + + ×1 x2 t2 xn tn

= s Chương trình cần dùng biến kt để kiểm tra xem tìm

Trang 34

được hay chưa, ban đầu kt:=False, nếu tìm được thì kt:=True và kết thúc chương trình mà không cần tìm tiếp nữa

Trang 35

4 Dạng 3 Tìm nghiệm tối ưu thoả mãn điều kiện

4.1 Nghiệm tối ưu

Một trong những bài toán đặt ra trong thực tế là việc

tìm ra một nghiệm thoả mãn một số điều kiện nào đó, là nghiệm tốt nhất theo một chỉ tiêu cụ thể Tuy nhiên cũng

cần phải nói rằng trong nhiều trường hợp chúng ta chưa thể xây dựng một thuật toán nào thực sự hữu hiệu để giải bài toán, mà cho tới nay việc tìm nghiệm của chúng

vẫn phải dựa trên mô hình liệt kê toàn bộ các cấu hình có

thể và đánh giá, tìm ra cấu hình tốt nhất

Mô hình thuật toán quay lui là tìm kiếm trên 1 cây phân cấp Nếu giả thiết rằng ứng với mỗi nút tương ứng với một giá trị được chọn cho xi sẽ ứng với chỉ 2 nút tương ứng với 2 giá trị mà xi+1 có thể nhận thì cây n cấp sẽ có tới 2n nút lá, con số này lớn hơn rất nhiều lần so với dữ liệu đầu vào n.

Chính vì vậy mà nếu như ta có thao tác thừa trong việc chọn xi thì sẽ phải trả giá rất lớn về chi phí thực thi thuật toán bởi quá trình tìm kiếm lòng vòng vô nghĩa trong các bước chọn kế tiếp xi+1, xi+2, Khi đó, một vấn đề

Trang 36

đặt ra là trong quá trình liệt kê lời giải ta cần tận dụng những thông tin đã tìm được để loại bỏ sớm những phương án chắc chắn không phải tối ưu Kỹ thuật đó gọi

là kỹ thuật đánh giá nhánh cận trong tiến trình quay lui.

Trang 37

4.2 Kỹ thuật nhánh cận

Dựa trên mô hình thuật toán quay lui,

ta xây dựng mô hình sau:

Trang 38

If (Việc thử trên vẫn còn hi vọng tìm ra cấu hình tốt

hơn CAUHINH) then

If (xi là phần tử cuối cùng

trong cấu hình) then

CAUHINH>

Trang 39

<Ghi nhận việc thử xi = j (nếu cần)>;

Try(i + 1); {Gọi đệ quy, chọn tiếp xi+1}

<Bỏ ghi nhận việc thử cho xi = j (nếu cần)>;

Trang 41

hơn cấu hình CAUHINH thì thử giá trị khác ngay mà không cần phải gọi đệ quy tìm tiếp hay ghi nhận kết quả, vì nếu

có tiếp tục thì việc làm đó là vô nghĩa và làm cho chi phí của bài toán càng lớn Nghiệm của bài toán sẽ được làm tốt dần, bởi khi tìm ra một cấu hình mới (tốt hơn CAUHINH), ta không in kết quả ngay mà sẽ cập nhật CAUHINH bằng cấu hình mới vừa tìm được.

Trang 42

VÍ DỤ 1 BÀI TOÁN MÁY RÚT TIỀN TỰ ĐỘNG ATM 2

Một máy ATM hiện có n (n ≤ 20) tờ tiền có mệnh giá t1, t2, t3,…., tn Hãy tìm cách trả ít tờ nhất với số tiền đúng bằng s.

Input: Tệp ATM.INP có dạng:

- Dòng đầu là hai số n và s.

- Dòng thứ hai gồm n số t1, t2, t3,…., tn

Output: Tệp ATM.OUT có dạng: Nếu có thể trả đúng s thì

đưa ra số tờ ít nhất cần trả và đưa ra cách trả, nếu không ghi -1.

Trang 43

Như ta đã biết nghiệm của bài toán là một dãy nhị phân độ dài n, giả sử đã xây dựng được k thành phần (x1, x2, , xk ), đã trả được tong và sử dụng c tờ Để đánh giá được các nghiệm mở rộng của (x1, x2, , xk ), ta nhận thấy:

tong s

tong s

mà lớn hơn hoặc bằng số tờ của cách trả tốt nhất hiện có thì không cần mở rộng các nghiệm (x1, x2, , xk ) nữa.

VÍ DỤ 2 BÀI TOÁN NGƯỜI DU LỊCH

Cho n thành phố đánh số từ 1 đến n và m tuyến đường giao thông hai chiều giữa chúng, mạng lưới giao thông này được cho bởi bảng C cấp n x n, ở đây Cij = Cji = Chi phí đi đoạn đường trực tiếp từ thành phố i đến thành

Ngày đăng: 25/06/2016, 01:08

TỪ KHÓA LIÊN QUAN

w