đà 2 Trường Đại học Bách khoa - ĐHQGHCM co Khoa Khoa hoc va Kĩ thuật mấy tính 1 Thuật toán quay lui Backtracking Algorithm 1.1 Giới thiệu Thuật toán quay lui là một kỹ thuật giải quy
Trang 1
DAI HOC QUOC GIA THANH PHO HO CHÍ MINH
TRUONG DAI HOC BACH KHOA KHOA KHOA HOC VA KY THUAT MAY TINH
000
CẤU TRÚC RỜI RẠC CHO KHMT(CO1007)
BÀI TẬP LỚN
TRAVELLING SALESMAN PROBLEM
GV hướng dẫn: Mai Xuân Toàn
TP Hồ Chí Minh, Tháng 6/2024
Trang 2Muc luc
1 Thuật toán quay lui (Backtracking Algorithm)
11 Giới thiệu HQ và và và
`“
1.3 Mã giả (Pseudo Code) .ẶẶ QẶ Q Sc
2_ Một số bài toán sử dụng thuật toán quay lui
2.1 Sinh các tập con từ một tập có Ñ phần tử
2.2 Sinhhoénvi 0
3 Ki thuat nhanh can (Branch and bound)
3.1 Gidithiéu 2
3.2 Ytudng 2 ee
4_ Bài toán người bán hang (Travelling salesman problem)
41 Phântích oxi
42 Code .-aaaa TH La V
Cấu trúc rồi rạc cho KHMT (C01007), HK232 Trang 1/8
Trang 3đà 2 Trường Đại học Bách khoa - ĐHQGHCM
co Khoa Khoa hoc va Kĩ thuật mấy tính
1 Thuật toán quay lui (Backtracking Algorithm)
1.1 Giới thiệu
Thuật toán quay lui là một kỹ thuật giải quyết vấn đề bằng cách tìm kiếm lời giải một cách từng bước thông qua việc thử các lựa chọn khác nhau và quay lại
nếu các giải pháp đưa ra chưa thỏa mã được yêu cầu
Quay lui thường được sử dụng trong các tình huống cần khám phá nhiều khả năng để giải quyết vấn đề, như tìm đường trong mê cung hoặc giải các câu đỗ như Sudoku Khi gặp ngõ cụt, thuật toán sẽ quay lui về điểm quyết định trước đó và khám phá một con đường khác cho đến khi tìm được lời giải hoặc tất cả các khả năng đã được kiểm tra hết
Đây là thuật toán thường dùng để giải các bài toán liệt kê 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ả khả năng
Quay lui được ứng dụng để giải các bài toán như: giải Sudokn, bài toán xếp hậu, liệt kê dãy nhị phân độ dài », liệt kê hoán vị của n phần tử, tìm kiếm đường
đi trong đồ thị, Tuy nhiên, độ phức tạp thời gian của thuật toán thường cao và phụ thuộc vào số lượng lựa chọn và cấu trúc của bài toán
1.2 Ý tưởng
Thuật toán quay lui hoạt động bằng cách đệ quy khám phá tất cả các giải pháp
có thể cho một vấn đề Thuật toán bắt đầu bằng cách chọn một giải pháp ban đầu, sau đó khám phá tất cả các phần mở rộng có thể của giải pháp đó Nếu một phần
mở rộng dẫn đến một giải pháp thỏa mãn, thuật toán sẽ trả về giải pháp đó Nếu một phần mở rộng dẫn đến một giải pháp không thỏa mãn, thuật toán sẽ quay lui
về giải pháp trước đó và thử một phần mở rộng khác
Dưới đây là một phác thảo chung về cách một thuật toán quay lui hoạt động:
1 Chọn một giải pháp ban đầu
2 Kham phá tất cả các phần mở rộng có thể của giải pháp hiện tại
3 Nếu một phần mở rộng dẫn đến một giải pháp, trả uề giải pháp đó
4 Nếu một phần rnở rộng không dẫn đến một giải pháp, quay lui uề giải pháp trước đó uà thủ một phần mnỏ rộng khác
5 Lặp lại các bước 2-4 cho đến khi tất cả các giải pháp có thể đã được khám phá
Bản chất của quay lui là một quá trình tìm kiếm theo chiều sâu (Depth-Pirst Search), đi theo chiều sâu để xác định dần z; và quay lui khi không còn z;¡ phù hợp
Cấu trúc rồi rạc cho KHMT (C01007), HK232 Trang 2/8
Trang 4
1.3
phương an chon i(thudc tập D Chap nhan i
Chon i cho X[k Thành công Đưa ra kết quả];
Backtracking(k+1) ;
Bo chon i cho X[k]];
&Ì Bước khởi tạo: Bắt đầu với một trạng thái ban đầu và khởi tạo các biến cần
thiết
§` Kiểm tra điều kiện đừng: Kiểm tra xem đã đạt được điều kiện dừng của bài toán
hay chưa Điều kiện này có thể là việc tìm thấy giải pháp hoặc đã thử tất cả các
lựa chọn mà không tìm được giải pháp
b! Lua chon va kiém tra ràng buộc: Chọn một lựa chọn trong không gian tìm kiếm
và kiểm tra xem lựa chọn đó có thỏa mãn các ràng buộc hay không Nếu không thỏa mãn, quay lại và thử lựa chọn khác
° Cập nhật trạng thái: Cập nhật trạng thái của bài toán dựa trên lựa chọn đã chọn Có thể cập nhật các biến, mảng, hoặc cấu trúc dữ liệu khác để thể hiện giải pháp hiện tại
Cấu trúc rồi rạc cho KHMT (C01007), HK232 Trang 3/8
Trang 5đà 2 Trường Dai hoc Bach khoa - DHQGHCM
co Khoa Khoa hoc va Kĩ thuật mấy tính
ê guu: Thực hiện dé quy dé tiép tuc tìm kiếm các lựa chọn tiếp theo Quá trình
6! Đệ zuy: Thực hiện đệ quy để tiếp tục tìm k lựa chọn tiếp tÍ trink
đệ quy sẽ được lặp lại cho đến khi tìm được giải pháp hoặc không còn lựa chon nào khả thi
wœw lui: Khi đã thử tất cả các lựa chọn hoặc không thé tié uc, quay lai tran,
° y lui: Khi đã thử tất lựa chọn hoặc không thể tiếp tục, quay lại trạng
thái trước đó và thử các lựa chọn khác Quá trình này được gọi là quay lui và cho phép ta khám phá các lựa chọn khác mà chưa được thử
tả uê kết quả: Trả về giải pháp tìm được khi thuật toán kết thúc
b` Trả oê kết quả: T giải pháp tìm được khi thuật toán kết tÌ
2_ Một số bài toán sử dụng thuật toán quay lui
2.1 Sinh các tập con từ một tập có N phần tử
Bài toán : Cho một mảng Arr[] kích thước N, hãy in ra tất cả các tập con của
mang Vi dụ với N = 3, Arr = [1, 2, 3| thì ta sinh được các tap con: {1}; {1, 2};
{1, 2, 3}; {1, 3}; {2h 12 3h 131
Phân tích : Số lượng tập con của một mảng có kích thước N = 2" Gia sit mét mảng có kích thước 3 chứa các phần tử {1, 2, 3}, cây không gian trạng thái có thể được xây dựng như sau:
—> Flement Included
1 2 3
txcludel] J | 2 | 3 Include !| ] | 2 | 3 |
Exclude 2[ ] Include 2 Exelude 2| - | Include 2
1 2.3 1) 2) 3 1.2.3 1213
EF27IREEIHNHHBNMEHBHEHRHHBNE.EBRHHBRMEHE
Print all Subsets SG
Dưới đây là cách cây không gian trạng thái được xây dựng:
Bắt đầu từ nút gốc, ta zem sét phần tử đầu tiên (1):
1 Bao gồm 1 trong tập con
2 Loại trừ 1 khỏi tập con
Từ mỗi nút con ở bước trước, ta zem sét phần tủ tiếp theo (2):
1 Bao gồm 2 trong tập con
Cấu trúc rồi rạc cho KHMT (C01007), HK232 Trang 4/8
Trang 62 Loại trừ 2 khỏi tập con
Từ mỗi nút con ở bước trước, ta em sét phần tử cuối cùng (3):
1 Bao gồm 3 trong tập con
2 Loại trừ 3 khỏi tập con
#include <iostream>
using namespace std;
// Function to find the subsets of the given array
void findSubsets(int nums[], int n)
{
// Loop through all possible subsets using bit manipulation for (int i = @; i < (1 << n); i++) {
// Loop through all elements of the input array
for (int j = 6; j < nj j++) {
// Check if the jth bit is set in the current subset
if ((i & (1 << j)) !=@) {
// If the jth bit is set, add the jth element to the subset
cout << nums[j] << " "5
cout << endl;
}
// Driver Code
int main()
int arr[] = { 1, 2, 3 };
int n = sizeof(arr)/sizeof(arr[9]);
findSubsets(arr, n);
2.2 Sinh hoán vị
Đài toán : Liệt kê tất cả các hoán vị của 1, 2, 3, , n Ví dụ, với ø = 3 ta có 123,
132, 213, 231, 312, 321
Phân tích : Chúng ta sẽ dùng một mảng A[n+1| lưu các hoán vị, khi đó các hoán
vị sẽ được biều diễn như sau:
Af1], A[2], A[3], .,A[n]
Trong đó Alil 4 A[j] V6i moi i,j e [1,n| và ¡ # j
Để xác nhận một phần tử chỉ được dùng một lần ta sẽ dùng mảng Bool để lưu
đánh dẫu Nếu phần tử chưa sử dụng thì sẽ có giá trị là 0 ngược lại sẽ có giá trị là
Cấu trúc rồi rạc cho KHMT (C01007), HK232 Trang 5/8
Trang 7đà 2 Trường Dai hoc Bach khoa - DHQGHCM
co Khoa Khoa hoc va Kĩ thuật mấy tính
1 Ban đầu ta khởi tạo tất cả các phần tử trong mảng đều có giá trị là 0
Ý tưởng của phương pháp quay lui là chúng ta sẽ chọn ra một phần tử chưa sử dụng Lưu phần tử đó vào một cấu hình tổ hợp, sau đó đánh dấu nó đã sử dụng
Ta sẽ lặp lại công việc như trên đến khi đủ cấu hình cho một tổ hợp thì sẽ xuất
ra màn hình Sau khi xuất ra ta lại quay trở lại bước trước đó để đánh dấu là nó chưa được chọn
Ta có thể hình dung bài toán như hình vẽ sau: Với n=3 thì bài toán trở thành liệt kê các hoán vị của các phần tử 1, 2, 3 Các hoán vị được liệt kê theo thứ tự từ điển tăng dần như hình vẽ sau:
Cấu trúc rồi rạc cho KHMT (C01007), HK232 Trang 6/8
Trang 83 Ki thuật nhánh cận (Branch and bound)
3.1 Giới thiệu
Trong một số trường hợp, thay vì yêu cầu liệt kê tất cả các cách chọn thoả mãn,
ta sẽ phải tìm xem cách nào là phương án tốt nhất Khi đó, việc dùng phương pháp nhánh cận sẽ giúp chúng ta giải những bài toán như vậy Đây chính là một phương pháp cải tiến từ thuật toán quay lui sử dụng để tìm nghiệm của bài toán tối wu
Ỏ phần trả về kết quả của quay lui, thay vì in ra hoặc lưu lại tất cả kết quả trong mỗi lần tính toán, ta sẽ cập nhật lại trạng thái tốt nhất Nếu tại một bước, bất kỳ bước nào tiếp theo cũng không thể làm cho kết quả tốt hơn kết quả hiện
có, ta sẽ không đi tiếp và quay lui
3.2 Ý tưởng
Giống như phương pháp quay lui, chúng ta sẽ vẫn biển diễn các cấu hình dưới dạng {zi,#a,#3, ,#„} Tuy nhiên nếu như ở quay lui, chúng ta chỉ đơn thuần là chọn các phần tử sao cho không thể chọn tiếp được nữa và liệt kê nó ra, thì ở phương pháp này mỗi cấu hình hiện tại sẽ được đánh giá độ tối tru và đưa ra quyết định là đi tiếp hay quay lui
Giả sử đã xây dựng được cấu hình gồm ¿ phần tử {z,za, zs z;} và chuẩn bị thêm phần tử z;.¡ Nếu như bạn đánh giá chính xác độ tối tu của cấu hình sau khi thém 241, ti+2, và biết được cấu hình {z1,z2, #3, ,#¡, #z+1, #2} không thể tốt hơn kết quả hiện có thì ta sẽ không thêm z;,¡ vào cấu hình và chuyên qua phần
tử khác
4_ Bài toán người bán hàng (Travelling salesman problem)
4.1 Phân tích
— Khởi tạo :
Biến int ans lưu độ dài đường đi ngắn nhất, int đ tính độ dài của đường đi hién tai, string best_ path lưu đường đi ngắn nhất và int emin dùng để lưu
trọng số nhỏ nhất khác 0 trong ma trận
Do mỗi đỉnh người bán hang chi di qua 1 lan nén ta sé tao ra mang int visited/]
để đánh dẫu đỉnh đã đi qua (phần tử trong mảng có giá trị bằng 1 khi đã đi qua
và bằng 0 khi chưa đi qua) Do vậy, ban đầu khi khởi tạo thì đỉnh bắt đầu có giá trị là 1 và các đỉnh còn lại có giá trị là 0
— Lựa chọn và kiểm tra:
Cấu trúc rồi rạc cho KHMT (C01007), HK232 Trang 7/8
Trang 9đà 2 Trường Đại học Bách khoa - ĐHQGHCM
co Khoa Khoa hoc va Kĩ thuật mấy tính
Kiểm tra tất cả các đỉnh và đỉnh tiếp theo sẽ được chọn nếu có đường đi từ đỉnh hiện tại đến đỉnh đó (trọng số trong e khác 0) và đỉnh đó chưa được di qua
— Quay lui:
Sau khi đi qua tất cả các đỉnh trong đồ thị ta sẽ kiểm tra xem có đường đi từ đỉnh cuối cùng đến đỉnh bắt đầu hay không, nếu có thì ta sẽ so sánh độ dài của đường đi hiện tại với độ dài đường đi ngắn nhất Sau khi so sánh thì ta sẽ quay lui
và xét đường đi tiếp theo Cứ tiếp tục như vậy ta sé có được đường đi ngắn nhất
Khi xét một đường đi mà đ + cminx(n—i+1)>ans (n là số đỉnh của đồ thị và
¡ là số đỉnh người bán hàng đã đi qua) thì ta sẽ dừng và xét đường đi khác
Cấu trúc rồi rạc cho KHMT (C01007), HK232 Trang 8/8
Trang 104.2 Code
——\void Try(int i, int n, char start, string res) { —— ] for(int j = 1; j <= n; j++) {
] if (visited[j] == 0 && c[X[i - 1]][3] != 9) (
visited[j] = 1;
x{i) = 3:
res += char(X[i] - 1 + 65);
d += c[X[i - 1]][X[i]] ;
] 1F(¡ “= n) {
] if(ans > d + c[X[n]][int(start - 'A' + 1)]) ({
ans = d + c[X[n]] [int(start - ‘A’ + 1)];
best_path = res;
} }
Try(i + 1, n, start, res);
}
visited[j] = 0;
d -= c[X[i - 1]][X[i]];
res.pop_back() ; res.pop_back() ;
; }
sẽ
]string Traveling(int g[20][20], int n, char start) {
nhap2(n, g);
string res = "";
int tmp = int(start - 'A') + 1;
X[1] = tmp;
visited[tmp] = 1;
Try(2, n, start, res);
best path.insert(0, 1, char(tmp - 1 + 65));
best_path += char(tmp - 1 + 65);
string best = best_path;
best_path = "";
ans = 100000000;
Sal£ st;
return best;
Cấu trúc rồi rạc cho KHMT (C01007), HK232 Trang 9/8
Trang 11Trường Đại học Bách khoa - ĐHQGHCM
co Khoa Khoa hoc va Kĩ thuật mấy tính
Input: Output:
9 20 35 42
29 0 34 30
35 34 0 12
42 39 12 9
Số đỉnh V: 4
Đỉnh xuất phát: A
Ma trén G: AFDELHKCJBGIA
@ 17 40 100 32 11 29 77 73 53 52 72
48 0 23 42 81 5 12 37 31 55 18 66
79 53 66 @ 8 97 38 61 48 76 75 71
45 86 82 20 23 @ 96 100 44 84 45 97
15 53 93 53 80 7 @ 29 21 78 13 43
87 9 1 26 26 44 98 @ 92 49 9 77
3@ 29 66 93 28 9 76 73 @ 73 91 92
35 61 19 45 24 16 94 33 53 90 @ 62
Số đỉnh V: 12
Đỉnh xuất phát: A
Cấu trúc rồi rạc cho KHMT (C01007), HK232 Trang 10/8