Duyệt vét cạn - BacktrackingQuay lui, vét cạn, thử sai, duyệt… là một số tên gọi tuy không đồng nghĩa nhưngcùng chỉ một phương pháp trong tin học: tìm nghiệm của một bài toán bằng cáchxe
Trang 1MỤC LỤC
Phương pháp duyệt
Chuyên đề 1 Duyệt vét cạn 1Chuyên đề 2 Duyệt nhánh cạnh 12Chuyên đề 3 Duyệt ưu tiên 24
Trang 2PHƯƠNG PHÁP DUYỆT Chuyên đề 1 Duyệt vét cạn - Backtracking
Quay lui, vét cạn, thử sai, duyệt… là một số tên gọi tuy không đồng nghĩa nhưngcùng chỉ một phương pháp trong tin học: tìm nghiệm của một bài toán bằng cáchxem xét tất cả các phương án có thể Đối với con người phương pháp này thườngkhông khả thi vì số phương án cần kiểm tra 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ápquay lui vét cạn Người đầu tiên đề ra chiến lược này là nhà toán học người MỹDerrick Henry Lehmer (1905 – 1991) vào những năm 1950
Ưu điểm của phương pháp quay lui, vét cạn là luôn bảo đảm tìm ra nghiệm đúng,chính xác Tuy nhiên, hạn chế của phương pháp này là thời gian thực thi lâu, độphức tạp lớn
Về bản chất, tư tưởng của phương pháp này là thử từng khả năng cho đến khi tìm thấy lời giải đúng Đó là một quá trình tìm kiếm theo độ sâu trong một tập các lời giải Trong quá trình tìm kiếm, nếu gặp một hướng lựa chọn không thỏa mãn, ta quay lui, về điểm lựa chọn có các hướng khác và thử hướng lựa chọn tiếp theo.
Khi đã thử hết tất cả các hướng lựa chọn xuất phát từ một điểm, ta quay lại điểmlựa chọn kế trước Quá trình tìm kiếm kết thúc khi không còn hướng lựa chọn nào
<Ghi nhận việc xi nhận giá trị t>;
<try(i+1)>; {th bước đi tiếp theo}
<Hủy bước đi thứ i (nếu cần)>;
Trang 3Phân tích:
Dãy nhị phân có độ dài n có dạng (x1, x2, …, xn) với xi∈ {0, 1}, 1 ≤ ≤ Như vậy,tại bước thứ i, ta tìm cách chọn giá trị cho biến xi
{Chuong trinh cai dat thuat toan de quy}
{Liet ke tat ca cac cau hinh nhi phan co do dai n}
for k:=1 to n do write(h[k]);
writeln;
endelseTry(i+1);
- Như vậy, việc xây dựng mỗi hoán vị được thực hiện qua n bước.
- Bước thứ i ta chọn một số trong tập {1, 2, …, n} để đặt vào vị trí thứ i của hoán vị.
- Tuy nhiên, ta chỉ chọn được số xi khi nó chưa được chọn cho các vị trítrước đó
Ta sử dụng mảng đánh dấu như sau:
Với ý nghĩa:
- KT[i] = True nếu i chưa được chọn
Trang 4- KT[i] = False nếu i đã được chọn{Chuong trinh cai dat thuat toan de quy}
{Liet ke tat ca cac hoan vi cua tap (1,2, ,n)}
for k:=1 to n do write(h[k],' ');
writeln;
endelseTry(i+1);
Trang 5Mỗi tổ hợp chập k của n phần tử có dạng (x1, x2, …, xk) trong đó:
- xilà một giá trị nằm trong tập {1, 2, …, n}
- vì tập hợp không phân biệt thứ tự nên ta sắp xếp các phần tử theo thứ tựtăng dần, vì vậy ràng buộc xi< xi+1với mọi giá trị i từ 1 đến k-1
- ứng cử viên xiđược chọn từ tập giá trị {xi-1+ 1, , n – (k-i)}
- nguyên tắc chọn trên giúp ta khỏi cần phải dánh dấu, bởi vì việc chọn giátrị tiếp theo phần tử đã được chọn trước đó nên sẽ không bị lặp lại
Chương trình
{chuong trinh de quy quay lui}
{liet ke tat ca cac to hop chap k cua tap n phan tu}
Chỉnh hợp lặp chập k của n phần tử là một dãy gồm 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ử, không yêu cầu các thành phần là khác nhau và
có phân biệt thứ tự của các cấu hình
Ví dụ, một dãy nhị phân có độ dài 3 là một chỉnh hợp lặp chập 3 của tập 2 phần tử{0, 1} Các dãy nhị phân có độ dài 3:
000, 001, 010, 011, 100, 101, 111
Trang 6Vì có phân biệt thứ tự nên cấu hình 001 khác với 010.
Như vậy, cách tìm nghiệm của bài toán chỉnh hợp lặp như sau:
- Mỗi chỉnh hợp lặp chập k của tập n phần tử có dạng (x1, x2, …, xk)
- xilà một giá trị lấy trong tập {1, 2, …, n}
- không có ràng buộc nào giữa các thành phần
{chuong trinh de quy quay lui}
{liet ke tat ca cac chinh hop lap chap k cua 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à chỉnh hợp không lặp chập n của n
Như vậy, cách tìm nghiệm của bài toán như sau:
- Mỗi nghiệm của bài toán là một dãy gồm k thành phần (x1, x2, …, xk)
Trang 7- Mỗi thành phần xilà một giá trị lấy trong tập {1, 2, …, n}
- Các giá trị đôi một khác nhau, để kiểm soát ràng buộc này, ta sử dụng mảng đánhdấu ok với ý nghĩa như sau:
Ok[j] = true có nghĩa rằng j sẽ chọn được
Ok[j] = false thì không chọn được, vì đã chọn j cho các vị trí trước đó
* Chương trình như sau:
{Chuong trinh de quy quay lui
liet ke tat ca cac chinh hop ko lap}
6 Bài tập 6: Bài toán xếp tám quân hậu
Một bàn cờ quốc tế là một bảng hình vuông gồm 8 hàng, 8 cột Quân hậu là mộtquân cờ có thể ăn được bất kỳ quân nào trên cùng một hàng, cùng một cột haymột đường chéo Hãy xếp tám quân hậu trên bàn cờ sao cho không có quân hậunào có thể ăn được quân hậu nào
Giải:
Trang 8- Theo bài toán, trên mỗi cột (j=1 8) của bàn cờ sẽ được đặt 1 quân hậu.
- Như vậy với mỗi cột ta phải tìm dòng thứ i nào đấy để đặt quân hậu vào Có
- Đường chéo song song với đường chéo phụ đi qua ô [i,j] chưa có hậu
- Khi đó, thủ tục try(j) thực hiện nhiệm vụ chọn dòng thứ i nào đấy để đặtquân hậu thứ j vào ô [i,j]
- Ta có thể minh họa một bàn cờ như sau:
Trang 9- Đánh dấu trạng thái các đường chéo // với đường chéo phụ
- Để lưu giữ kết quả, ta sử dụng mảng một chiều x
{Chuong trinh de quy quay lui
liet ke moi nghiem cua bai toan 8 quan hau}
Trang 107 Bài tập 7: Bài toán máy rút tiền tự động ATM
Một máy ATM hiện có n ( ≤ 20) tờ tiền có giá t1, t2, …, tn Hãy đưa ra một cách trảvới số tiền đúng bằng s
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, bằng 0 trong trường hợp ngược lại (x1, x2, …, xn)
là nghiệm nếu 1 1+ 2 2+ ⋯ +
* Chương trình:
{Chuong trinh de quy quay lui
giai bai toan may rut tien tu dong ATM}
Program AtmSolution;
const
fi='atm.inp';
Trang 11if sum = s then ghinghiem;
if (sum<s)and(i<n) then atm(i+1);
if ok=true then exit;
Trang 12Cho bàn cờ n x n ô, tìm cách di chuyển một quân mã (mã di chuyển theo luật cờvua) trên bàn cờ xuất phát từ ô (1, 1) đi qua tất cả các ô, mỗi ô qua đúng 1 lần.
1.2 Số siêu nguyên tố (nguồn bài: Tài liệu giáo khoa chuyên tin Q1)
Số siêu nguyên tố là số nguyên tố mà khi bỏ bớt một số tùy ý các chữ số bên phảicủa nó thì phần còn lại vẫn là một số nguyên tố
Ví dụ 2333 là một số siêu nguyên tố có 4 chữ số vì 233, 23, 2 cũng là các sốnguyên tố Cho số nguyên dương N (0 < < 10), đưa ra các số siêu nguyên tố có
N chữ số cùng số các số đó
Ví dụ với N = 4 có 16 số:
2333, 2339, 2393, 2399, 2939, 3119, 3137, 3733, 3739, 3793, 3797, 5939, 7193,
7331, 7333, 7393
1.3 Chèn phép toán (nguồn bài: Tài liệu giáo khoa chuyên tin Q1)
Cho một xâu S chỉ gồm các ký tự từ ‘0’ đến ‘9’, độ dài nhỏ hơn 10 và số nguyên m,hãy đưa ra một cách chèn vào S các dấu ‘+’ hoặc ‘ -‘ để thu được số m cho trước(nếu có thể)
Ví dụ, M=8, S = ‘123456789’ thì một cách chèn là: ‘ -1+2-3+4+5-6+7-8+9’
1.4 Phân tích số (nguồn bài: Tài liệu giáo khoa chuyên tin Q1)
Cho n số nguyên dương a1, a2, …, an ( ≤ 10, ≤ 109) Tìm số nguyên dương mnhỏ nhất sao cho m không phân tích được dưới dạng tổng của một số các sốthuộc n số trên (mỗi số sử dụng không quá một lần)
D ữ liệu v ào K ết quả
n = 4
dãy số:
1, 2, 3, 6
13
Trang 13Chuyên đề 2 Duyệt nhánh cận
Trong thực tế, có nhiều bài toán yêu cầu tìm ra một phương án thỏa mãn một sốđiều kiện nào đó, và phương án đó là tốt nhất theo một tiêu chí cụ thể Các bàitoán như vậy được gọi là bài toán tối ưu Có nhiều bài toán tối ưu không có thuậttoán nào thực sự hữu hiệu để giải quyết, mà cho đến nay vẫn phải dựa trên môhình xem xét toàn bộ các phương án, rồi đánh giá để chọn ra phương án tốt nhất.Phương pháp nhánh và cận là một dạng cải tiến của phương pháp quay lui, được
áp dụng để tìm nghiệm của bài toán tối ưu
Giả sử nghiệm của bài toán có thể biểu diễn dưới dạng một véctơ (x1, x2, …, xn),mỗi thành phần xi(i = 1, 2, …, n) được chọn ra từ tập Si Mỗi nghiệm của bài toán X
= (x1, x2, …, xn) được xác định độ tốt bằng một hàm f(X) và mục tiêu cần tìmnghiệm X để f(X) đạt giá trị nhỏ nhất (hoặc lớn nhất)
Tư tưởng của phương pháp nhánh và cận như sau: Giả sử đã xây dựng được kthành phần của nghiệm (x1, x2, …, xk) và khi mở rộng nghiệm (x1, x2, …, xk+1), nếubiết rằng tất cả các nghiệm mở rộng của nó (x1, x2, …, xk+1, …) đều không tốt bằngnghiệm tốt nhất đã biết ở thời điểm trước đó, thì ta không cần mở rộng từ (x1, x2,
…, xk) nữa Như vậy, với phương pháp nhánh và cận, ta không phải duyệt toàn bộcác phương án để tìm ra nghiệm tốt nhất mà bằng cách đánh giá các nghiệm mở
rộng, ta có thể cắt bỏ những nhánh không cần thiết, do đó việc tìm nghiệm tối ưu
sẽ nhanh hơn Cái khó nhất trong việc áp dụng phương pháp nhánh và cận làđánh giá các nghiệm mở rộng, nếu đánh giá được tốt sẽ giúp bỏ qua được nhiềuphương án không cần thiết, khi đó thuật toán nhánh cận sẽ chạy nhanh hơn nhiều
so với thuật toán vét cạn
Thuật toán nhánh và cận có thể mô tả bằng mô hình đệ quy sau:
Procedure BranchBound(i); {xây dựng thành phần thứ i}
Trang 14mới tìm thấy tốt hơn BestSolution thì BestSolution sẽ được cập nhật lại là nghiệmmới tìm được.
1 Bài toán máy rút tiền tự động ATM
Output: Tệp ATM.OUT có dạng: Nếu có thể trả tiền đúng bằ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
Như đã biết, nghiệm của bài toán là một dãy nhị phân có độ dài n, giả sử đã xâydựng được k thành phần (x1, x2, …,xk), đã trả được sum và sử dụng c tờ tiền Đểđánh giá các nghiệm mở rộng của (x1, x2, …,xk) ta nhận thấy:
Trang 16if xbest[j]=1 then write(f,t[j],' ');
2 Bài toán người du lịch
Bài toán: Cho n thành phố được đánh số từ 1 đến n và các 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 mảng C[1 n,1 n], ở đây Cịj = Cji là chi phí đi đoạn đường trực tiếp từ thành phố i đến thànhphố j (hoặc ngược lại)
Một người du lịch xuất phát từ thành phố 1, muốn đi thăm tất cả các thành phốcòn lại mỗi thành phố đúng 1 lần và cuối cùng quay lại thành phố 1 Hãy chỉ ra chongười đó hành trình với chi phí ít nhất Bài toán được gọi là bài toán người du lịch
hay bài toán người chào hàng (Travelling Salesman Problem – TSP).
Ví dụ 2
Trang 17TSP.INP TSP.OUT Hình ảnh minh họa
Giải
1) Hành trình cần tìm có dạng (x1= 1, x2, …, xn, xn+1= 1), ở đây giữa xivà xi+1:hai thành phố liên tiếp trong hành trình phải có đường đi trực tiếp; trừthành phố 1, không thành phố nào được lặp lại hai lần, có nghĩa là dãy (x1,
x2, …, xn) lập thành một hoán vị của (1, 2, …, n)
2) Duyệt quay lui: x2có thể chọn một trong các thành phố mà x1có đường đitrực tiếp tới, với mỗi cách thử chọn x2như vậy thì x3có thể chọn một trongcác thành phố mà x2có đường đi tới (ngoài x1) Tổng quát: xicó thể chọn 1trong các thành phố chưa đi qua mà xi-1 có đường đi trực tiếp tới(2 ≤ ≤ )
3) Nhánh cận: Khởi tạo cấu hình BestSolution có chi phí bằng +∞ Với mỗibước thử chọn xi xem chi phí đường đi cho tới lúc đó có nhỏ hơn chi phícủa cấu hình BestSolution không? Nếu không nhỏ hơn thì thứ giá trị khácngay bởi có đi tiếp cũng chỉ tốn thêm Khi thử được một giá trị xn ta kiểmtra xem xncó đường đi trực tiếp về 1 hay không? Nếu có đánh giá chi phí đi
từ thành phố 1 đến thành phố xn cộng với chi phí từ xntrực tiếp về 1, nếunhỏ hơn BestSolution thì cập nhật lại BestSolution bằng cách đi mới
Trang 192.1 Bài tập 4.15 (nguồn bài: Tài liệu giáo khoa chuyên tin Q1)
Lời giải bài toán người du lịch ở trên là một giải pháp nhánh cận rất thô sơ Nếuchạy chương trình với trường hợp: số thành phố n=20, khoảng cách giữa cácthành phố bằng 1 (nghĩa là c[i, j]=1 với i<>j) Khi đó chương trình không cho rađược kết quả vì độ phức tạp rất lớn 20!, không thể chạy trong thời gian cho phép
Ta nên cải tiến cách đánh giá như sau:
Để đi qua tất cả các thành phố, sau đó quay lại thành phố 1 ta phải đi qua n tuyếnđường (qua tổng cộng n+1 điểm, vì thành phố 1 được tính 2 lần) Giả sử ta đã xâydựng hành trình đi qua i thành phố với tổng chi phí là sum, ta gọi min là chi phícủa cạnh nhỏ nhất trong các cạnh chưa đi qua Nếu như sum + (n -i+1)*min
>=best thì ta không nên xây dựng tiếp hành trình từ thành xinữa mà nên quay lui
để chọn hướng đi khác để hi vọng có được hành trình tốt hơn
Để dễ dàng khi tìm min trong các cạnh chưa xét, ta xây dựng danh sách cạnh gồm
½ số cạnh nằm phía trên đường chéo chính (i<j) và sắp xếp theo thứ tự tăng dần
2.2 Bài tập 4.16 (nguồn bài: Tài liệu giáo khoa chuyên tin Q1)
Cho bàn cờ quốc tế 8 x 8 ô, mỗi ô ghi một số nguyên dương không vượt quá
32000 Hãy xếp 8 quân hậu lên bàn cờ sao cho không có quân nào khống chếđược quân nào và tổng các số ghi trên các ô mà quân hậu đứng là lớn nhất
Input: tệp gồm 8 dòng, mỗi dòng ghi 8 số nguyên dương, giữa các số cách nhau
một dấu cách
Output: tệp có một số duy nhất là đáp số của bài toán.
Trang 20Như đã biết, trên mỗi cột của bàn cờ chỉ đặt được một quân hậu Để tìm nghiệmbài toán, ta phải duyệt quay lui:
- Tại bước thứ i, ta chọn một dòng j nào đấy để đặt quân hậu thứ i vào (với điềukiện dòng j, đường chéo // với đường chéo chính, đường chéo // với đườngchéo phụ đi qua ô đó chưa được đặt một quân hậu nào)
- Tuy nhiên, nếu duyệt tất cả các phương án sau đó tìm cách đặt tốt nhất trong
92 cách đặt thì không khả thi vì chươn g trình sẽ không đảm bảo về mặt thờigian
- Giả sử tới bước thứ i, ta đã đặt được i quân hậu với tổng giá trị là sum Gọimax[k] là giá trị lớn nhất của các ô chưa bị kiểm soát trên các cột còn lại:
max[k] = max{dk+1, …, dn}với dhlà giá trị lớn nhất của các ô chưa bị kiểm soát trên cột h
- Khi đó, nếu mở rộng nghiệm theo phương án này thì giá trị lớn nhất có thể đạtsum + max[k] * (n-i);
- Do vậy, nếu sum + max[k]*(n-i)<= BestSolution thì không cần mở rộng nghiệmtheo hướng này nữa
2.3 Xếp valy (nguồn bài: spoj)
Một va ly có thể chứa tối đa W đơn vị trọng lượng Có N loại đồ vật, số lượngmỗi loại không hạn chế Loại đồ vật thứ i có trọng lượng Ai và có giá trị Ci Hỏinên chọn những loại đồ vật nào và số lượng bao nhiêu để xếp vào va ly sao cho:
- Tổng trọng lượng của các vật không vượt quá giới hạn W của valy;
- Tổng giá trị của các vật là lớn nhất
Giải: Với mỗi loại đồ vật i, gọi Ti là giá trị riêng của nó: Ti = Ci / Ai Sau đó sắp các
loại đồ vật theo thứ tự giảm dần của Ti
Phương pháp duyệt nhánh cận tại mỗi bước duyệt loại đồ vật i, ta lấy k đồ vậtloạinày, khi đó điều kiện để duyệt tiếp loại đồ vật i+1 (điều kiện nhánh cận) là:
- k*Ai <= w
- s(i) + k*Ci + (w - k*Ai)*Ti+1 > smax
Trong đó:
- w là trọng lượng mà valy có thể chứa thêm sau bước duyệt loại đồ vật i-1;
- s(i) là tổng giá trị hiện đang có của valy sau bước duyệt loại đồ vật i-1;
- smax là tổng giá trị valy của một các xếp đã tìm được nhưng chưa tối ưu Cóthể khởi tạo smax ban đầu bằng 0
2 4 Xâu ABC
Tìm một xâu chỉ gồm các ký tự A,B,C sao cho
Trang 21- Có độ dài N cho trước (N<=1000)
- Hai đọan con bất kì liên nhau đều khác nhau (đoạn con là một dãy các ký tựliên tiếp của xâu)
- Có ít ký tự C nhất
Giải (thầy Lê Minh Hoàng):
Thuật toán 1: Ước lượng hàm cận
Ta sẽ dùng thuật toán quay lui để liệt kê các dãy n ký tự mà mỗi phần tử của dãyđược chọn trong tập {A, B, C} Giả sử cấu hình cần liệt kê có dạng x[1 n] thì:
Nếu dãy x[1 n] thoả mãn 2 đoạn con bất kỳ liền nhau đều khác nhau, thì trong 4 ký
tự liên tiếp bất kỳ bao giờ cũng phải có ít nhất một ký tự ‘C’ Như vậy với một đoạngồm k ký tự liên tiếp của dãy x[1 n] thì số ký tự ‘C’ trong đoạn đó luôn ≥ [4]
Sau khi thử chọn ∈ { , , , }, nếu ta đã có ký tự ‘C’ trong đoạn x[1 i], thì cho
dù các bước chọn tiếp sau làm tốt như thế nào chăng nữa, số ký tự ‘C’ phải chọnthêm không bao giờ ít hơn [ 4−] Tức là nếu theo phương án chọn như thế này thì
số ký tự ‘C’ trong dãy kết quả (khi chọn đến ) không thể ít hơn + [ 4−] Ta dùngcon số này để đánh giá nhánh cận, nếu nó nhiều hơn số ký tự ‘C’ trong cấu hình tốtnhất đang cho tới thời điểm hiện tại thì chắc chắn có làm tiếp cũng chỉ được mộtcấu hình tồi tệ hơn, ta bỏ qua ngay cách chọn này và thử phương án khác
Thuật toán này hoạt động khá nhanh với ≤ 100, tuy nhiên với những giá trị n lớnthì thời gian thực hiện vẫn tương đối lâu Dưới đây là một thuật toán tốt hơn, đi đôivới nó là một chiến lược chọn hàm cận hiệu quả hơn
Thuật toán 2: Lấy ngắn nuôi dài
Với mỗi độ dài m, ta gọi f[m] là số ký tự ‘C’ trong dãy thỏa hai đoạn con bất kỳ liềnnhau đều khác nhau và có ít ký tự C nhất Rõ ràng f[0] = 0, ta lập trình tính các f[m]khác với điều kiện là f[0 m-1] đã biết
Tương tự như thuật toán 1, ta giả sử cấu hình cần tìm có dạng x[1 m] thì sau khithử chọn xi, nếu ta đã có tiký tự ‘C’ trong đoạn x[1 i] thì dù cho các bước tiếp sau cólàm tốt thế nào đi chăng nữa, số ký tự ‘C’ chọn thêm sẽ không ít hơn f[m-i], tức lànếu chọn tiếp thì số ký tự ‘C’ sẽ không ít hơn + [ − ] Ta dùng cận này kết hợpvới thuật toán quay lui để tìm xâu tốiưu độ dài m
2.5 Tour du lịch rẻ nhất (TOUR)
Một khu thắng cảnh gồm n điểm đánh số từ 1
tới n (n ≤ 100) và m đường đi hai chiều giữa
các cặp địa điểm đó, chi phí đi trên các đường
đi là biết trước ( ≤ 10000) Một Tour du lịch là
một hành trình xuất phát từ một địa điểm đi
thăm ≥ 2 địa điểm khác và quay trở về điểm
xuất phát, ngoại trừ địa điểm xuất phát, không
địa điểm nào bị thăm tới hai lần Chi phí của một