ĐẠI HỌC THÁI NGUYÊN TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG NGUYỄN QUANG TRÌNH TỔ CHỨC DỮ LIỆU CHO LỚP CÁC THUẬT TOÁN QUAY LUI LUẬN VĂN THẠC SĨ KHOA HỌC MÁY TÍNH THÁI NGU
Trang 1ĐẠI HỌC THÁI NGUYÊN TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG
NGUYỄN QUANG TRÌNH
TỔ CHỨC DỮ LIỆU CHO LỚP CÁC THUẬT TOÁN QUAY LUI
LUẬN VĂN THẠC SĨ KHOA HỌC MÁY TÍNH
THÁI NGUYÊN - 2013
Trang 2ĐẠI HỌC THÁI NGUYÊN TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG
NGUYỄN QUANG TRÌNH
TỔ CHỨC DỮ LIỆU CHO LỚP CÁC THUẬT TOÁN QUAY LUI
Chuyên ngành: Khoa học máy tính
Trang 3LỜI CAM ĐOAN
Học viên xin cam đoan, kết quả của luận văn hoàn toàn là kết quả của
tự bản thân học viên tìm hiểu, nghiên cứu và thực hiện theo sự hướng dẫn khoa học của PGS.TSKH Nguyễn Xuân Huy
Các tài liệu tham khảo được trích dẫn và chú thích đầy đủ
Thái Nguyên, ngày 10 tháng 10 năm 2013
Học viên
Nguyễn Quang Trình
Trang 4LỜI CẢM ƠN
Học viên xin được bày tỏ lòng biết ơn chân thành và sâu sắc nhất đến thầy giáo PGS.TSKH Nguyễn Xuân Huy, người đã tận tình hướng dẫn và tạo mọi điều kiện tốt nhất để học viên có thể hoàn thành luận văn này
Xin chân thành cảm ơn các thầy giáo, cô giáo Trường Đại học Công nghệ thông tin và Truyền thông - Đại học Thái Nguyên, Viện Công nghệ Thông tin - Viện Khoa học và Công nghệ Việt Nam đã trực tiếp giảng dạy, giúp đỡ và tạo mọi điều kiện thuận lợi trong quá trình học tập và nghiên cứu
Cảm ơn các thầy cô giáo, các bạn học viên lớp cao học Khoa học máy tính CK10C, gia đình và các đồng nghiệp đã luôn quan tâm, hỗ trợ, khuyến khích trong suốt thời gian học tập và thực hiện đề tài
Xin chân thành cám ơn!
Học viên
Nguyễn Quang Trình
Trang 5MỤC LỤC
TRANG BÌA
LỜI CAM ĐOAN i
LỜI CẢM ƠN ii
MỤC LỤC iii
DANH MỤC CÁC HÌNH v
MỞ ĐẦU 1
1 Lí do chọn đề tài 1
2 Đối tượng và phạm vi nghiên cứu 1
3 Hướng nghiên cứu của đề tài 1
4 Những nội dung nghiên cứu chính 1
5 Phương pháp nghiên cứu 2
6 Ý nghĩa khoa học của đề tài 2
Chương 1 TỔNG QUAN THUẬT TOÁN QUAY LUI 3
1.1 Giới thiệu chung 3
1.2 Ý tưởng của thuật toán [1], [2], [3], [5] 3
1.3 Kết luận 7
Chương 2 XÂY DỰNG THUẬT TOÁN QUAY LUI VÀ TỔ CHỨC DỮ LIỆU CHO MỘT SỐ BÀI TOÁN KINH ĐIỂN 8
2.1 Bài toán từ chuẩn [2] 8
2.1.1 Giới thiệu bài toán 8
2.1.2 Tổ chức dữ liệu và chương trình 8
2.1.3 Nhận xét 11
2.2 Bài toán xếp hậu [1], [2] 12
2.2.1 Giới thiệu bài toán 12
2.2.2 Tổ chức dữ liệu và chương trình 13
2.2.3 Nhận xét 20
Trang 62.3 Bài toán đa giác 21
2.3.1 Giới thiệu bài toán 21
2.3.2 Tổ chức dữ liệu và chương trình 23
2.3.3 Nhận xét 29
2.4 Bài toán ô số Sudoku 30
2.4.1 Giới thiệu bài toán 30
2.4.2 Tổ chức dữ liệu và chương trình 32
2.4.3 Nhận xét 36
2.5 Kết luận 36
Chương 3 CÀI ĐẶT CHƯƠNG TRÌNH 37
3.1 Cài đặt cho bài toán từ chuẩn 37
3.1.1 Giới thiệu chương trình 37
3.1.2 Thử nghiệm chương trình 41
3.2 Cài đặt cho bài toán xếp hậu 42
3.2.1 Giới thiệu chương trình 42
3.2.2 Thử nghiệm chương trình 43
3.3 Cài đặt cho bài toán đa giác 45
3.3.1 Giới thiệu chương trình 45
3.3.2 Thử nghiệm chương trình 47
3.4 Cài đặt cho bài toán ô số Sudoku 48
3.4.1 Giới thiệu chương trình 48
3.4.2 Thử nghiệm chương trình 49
KẾT LUẬN 53
TÀI LIỆU THAM KHẢO 54
Trang 7DANH MỤC CÁC HÌNH
Hình 1.1 Cây tìm kiếm lời giải theo thuật toán quay lui 7
Hình 2.1 Cây tìm kiếm lời giải cho bài toán từ chuẩn 11
Hình 2.2 Lời giải 1 với N = 4 15
Hình 2.3 Lời giải 2 với N = 4 16
Hình 2.4 Cây lời giải bài toán xếp hậu với N = 4 17
Hình 2.5 Các đường chéo chính 18
Hình 2.6 Các đường chéo phụ 18
Hình 2.7 Nghiệm v1 = (2, 4, 1, 3) 20
Hình 2.8 Trò chơi Instant Insanity 21
Hình 2.9 Đáp án đạt được sau khi xoay mỗi khối sang trái 1 góc 90o 21
Hình 2.10 Bài toán đa giác với m = 4, n = 6 22
Hình 2.11 Đáp án của bài toán đa giác với m = 4, n = 6 23
Hình 2.12 Cách tìm nghiệm id = {1,5,6,3} 29
Hình 2.13 Đề bài 1 31
Hình 2.14 Đáp án đề bài 1 31
Hình 2.15 Đề bài 2 32
Hình 2.16 Đáp án đề bài 2 32
Hình 3.1 Giao diện chương trình TUCHUAN 41
Hình 3.2 Tìm 1 nghiệm với n = 7 41
Hình 3.3 Tìm 1 nghiệm với n = 100 41
Hình 3.4 Tìm 1 nghiệm với n = 1000 42
Hình 3.5 Giao diện chương trình XEPHAU 42
Hình 3.6 20 nghiệm đầu tiên 43
Hình 3.7 Các nghiệm 68 → 92 43
Hình 3.8 20 nghiệm đầu tiên 44
Trang 8Hình 3.9 Các nghiệm 699 → 724 44
Hình 3.10 Chương trình XEPHAU cải tiến 45
Hình 3.11 Giao diện chương trình DAGIAC 46
Hình 3.12 Thử nghiệm chương trình với M = 4, N = 6 47
Hình 3.13 Thử nghiệm chương trình với M = 10, N = 20 47
Hình 3.14 Thử nghiệm chương trình với M = 40, N = 40 48
Hình 3.15 Giao diện chương trình SUDOKU 49
Hình 3.16 Đọc đề bài từ tệp input de1 50
Hình 3.17 Đáp án de1 bằng phương án 1 50
Hình 3.18 Đáp án de1 bằng phương án 2 51
Hình 3.19 Đọc đề bài từ tệp input de2 52
Hình 3.20 Đáp án de2 bằng phương án 1 52
Hình 3.21 Đáp án de2 bằng phương án 2 52
Trang 9MỞ ĐẦU
1 Lí do chọn đề tài
Để giải một bài toán thông thường có nhiều cách tiếp cận Mỗi cách tiếp cận khác nhau cho kết quả với độ tối ưu khác nhau Với nhiều bài toán việc tìm ra giải thuật tối ưu không phải việc đơn giản, do đó một kĩ năng cần thiết để giải được một bài toán hoàn chỉnh là phải giải được bài toán ở kích thước dữ liệu vừa phải Đây sẽ là những bộ dữ liệu thử mang tính định hướng chiến lược cho việc giải bài toán Với phương pháp này có thể giải ngay bằng cách duyệt toàn bộ hoặc có thể giải được một phần lớn của bài toán Một thuật toán giúp duyệt toàn bộ hiệu quả, nhanh chóng là thuật toán quay lui
Việc áp dụng và cài đặt thuật toán quay lui cho các bài toán thường khá trừu tượng và khó hiểu Và khó hơn là việc kết hợp thuật toán quay lui với nhánh cận để giúp quá trình duyệt được hiệu quả hơn Do đó học viên thấy việc phân tích, đánh giá và định hướng cách tiếp cận một bài toán bằng thuật toán quay lui là rất cần thiết
Trong khuôn khổ luận văn thạc sỹ, học viên chọn đề tài nghiên cứu:
“Tổ chức dữ liệu cho lớp các thuật toán quay lui”
2 Đối tượng và phạm vi nghiên cứu
Tìm hiểu một số đặc trưng của lớp các bài toán đòi hỏi duyệt các khả năng
Ứng dụng để giải một số bài toán liệt kê và tìm phương án tối ưu
3 Hướng nghiên cứu của đề tài
Tìm hiểu các kỹ thuật và quy trình duyệt dữ liệu
Cài đặt chương trình cho một số bài toán
4 Những nội dung nghiên cứu chính
Chương 1 Tổng quan thuật toán quay lui
Chương này giới thiệu một số vấn đề liên quan đến đặc điểm, ý tưởng
và nội dung của thuật toán quay lui
Trang 10Chương 2 Xây dựng thuật toán quay lui và tổ chức dữ liệu cho một
số lớp bài toán kinh điển
Bài toán từ chuẩn
Bài toán xếp hậu
Bài toán đa giác
Bài toán ô số Sudoku
Chương 3 Cài đặt chương trình cho các bài toán ở Chương 2
và thử nghiệm
5 Phương pháp nghiên cứu
Phân tích, liệt kê, đối sánh, nghiên cứu tài liệu, tổng hợp các kết quả
của các nhà nghiên cứu liên quan đến lĩnh vực nghiên cứu
6 Ý nghĩa khoa học của đề tài
Vận dụng tốt thuật toán quay lui, giúp chúng ta có thể dễ dàng giải được các bài toán liệt kê, tối ưu
Xây dựng cơ sở khoa học cho các bài toán tìm kiếm
Trang 11Chương 1 TỔNG QUAN THUẬT TOÁN QUAY LUI
Chương này giới thiệu một số vấn đề liên quan đến đặc điểm, ý tưởng và nội dung của thuật toán quay lui
1.1 Giới thiệu chung
Thuật toán duyệt toàn bộ bằng cách sử dụng các vòng lặp lồng nhau có thể áp dụng cho các bài toán có kích thước của các tập nghiệm cố định Với những bài toán mà kích thước của nghiệm phụ thuộc vào dữ liệu đầu vào hoặc một số điều kiện nào khác thì việc sử dụng các vòng lặp lồng nhau là bất khả thi Lúc này, chỉ có thuật toán quay lui là có thể thực hiện duyệt qua được tất cả các bộ nghiệm của bài toán
Thuật toán quay lui là chiến lược tìm nghiệm bài toán bằng cách xét tất
cả các phương án có thể Đây là một thuật toán có thể áp dụng để giải rất nhiều bài toán với kích thước dữ liệu thích hợp Ưu điểm của thuật toán là đảm bảo tìm ra nghiệm đúng chính xác Tuy nhiên, hạn chế là độ phức tạp thường lớn
Những bài toán tìm một nghiệm, liệt kê hoặc bài toán tối ưu là những lớp bài toán có thể giải bằng thuật toán quay lui
1.2 Ý tưởng của thuật toán [1], [2], [3], [5]
Giả sử ta phải tìm trong một tập dữ liệu D cho trước một dãy dữ liệu:
v = (v[1], v[2], , v[n])
thoả đồng thời hai tính chất P và Q
Trước hết ta chọn một trong hai tính chất đã cho để làm nền, tính chất thứ hai tạm gác bỏ, giả sử ta chọn tính chất P
Sau đó ta thực hiện các bước sau đây:
Bước 1 (Khởi trị) Xuất phát từ một dãy ban đầu v = (v[1], , v[i]) nào
đó của các phần tử trong D sao cho v thoả P
Trang 12Bước 2 Nếu v thoả Q ta dừng thuật toán và thông báo kết quả là dãy v,
ngược lại ta thực hiện Bước 3
Bước 3 Tìm tiếp một phần tử v[i + 1] để bổ sung cho v sao cho
v = (v[1], , v[i], v[i + 1]) thoả P
Có thể xảy ra các trường hợp sau đây:
3.1 Tìm được phần tử v[i + 1]: quay lại bước 2
3.2 Không tìm được v[i + 1] như vậy, tức là với mọi v[i + 1] có thể lấy trong D, dãy v = (v[1], , v[i], v[i + 1]) không thoả P
Điều này có nghĩa là đi theo đường v = (v[1], , v[i]) sẽ không dẫn tới
kết quả Ta phải đổi hướng tại một vị trí nào đó
Để thoát khỏi ngõ cụt này, ta tìm cách thay v[i] bằng một giá trị khác
trong D
Nói cách khác, ta loại v[i] khỏi dãy v, giảm i đi một đơn vị rồi quay lại
bước 3
Cách làm như trên được gọi là quay lui: lùi lại một bước
Dĩ nhiên ta phải đánh dấu v[i] là phần tử đã loại tại vị trí i để sau đó không đặt lại phần tử đó vào vị trí i trong dãy v
Khi nào thì có thể trả lời là không tồn tại dãy v thoả đồng thời hai tính
chất P và Q? Nói cách khác, khi nào thì ta có thể trả lời là bài toán vô nghiệm?
Dễ thấy, bài toán vô nghiệm khi ta đã duyệt hết mọi khả năng Ta nói là
đã vét cạn mọi khả năng Chú ý rằng có thể đến một lúc nào đó ta phải lùi liên tiếp nhiều lần Từ đó suy ra rằng, thông thường bài toán vô nghiệm khi ta không còn có thể lùi được nữa Có nhiều sơ đồ giải các bài toán quay lui, dưới đây là hai sơ đồ khá đơn giản, không đệ quy
Trang 13Sơ đồ 1: Giải bài toán quay lui
Ghi nhận nghiệm;
exit;
end;
if (Hết khả năng duyệt) then
begin Ghi nhận vô nghiệm;
Có bài toán yêu cầu tìm toàn bộ (mọi nghiệm) các dãy v thoả đồng thời
hai tính chất P và Q Nếu biết cách tìm một nghiệm ta dễ dàng suy ra cách tìm mọi nghiệm như sau: mỗi khi tìm được một nghiệm, ta thông báo nghiệm đó trên màn hình hoặc ghi vào một tệp rồi thực hiện thao tác Lùi, tức là giả vờ
như không công nhận nghiệm đó, do đó phải loại v[i] cuối cùng trong dãy v
để tiếp tục tìm hướng khác
Trang 14Phương pháp này có tên là phương pháp giả sai Hai sơ đồ trên sẽ được sửa một chút như sau để tìm mọi nghiệm
Sơ đồ 3: Giải bài toán quay lui
begin
if d = 0 then Ghi nhận: vô nghiệm;
else Ghi nhận: d nghiệm;
Trang 15Quá trình tìm kiếm lời giải theo thuật toán quay lui có thể mô tả bởi cây tìm kiếm lời giải sau đây:
áp dụng thuật toán, đôi khi ta phải kết hợp thêm nhiều kĩ thuật, thuật toán khác thì mới có thể đem lại kết quả tốt nhất
Xét tiếp các khả năng của Bước 3
Trang 16Chương 2
XÂY DỰNG THUẬT TOÁN QUAY LUI VÀ TỔ CHỨC
DỮ LIỆU CHO MỘT SỐ BÀI TOÁN KINH ĐIỂN
Chương 2 sẽ trình bày cách tổ chức dữ liệu để có thế áp dụng thuật toán quay lui cho một số bài toán kinh điển
2.1 Bài toán từ chuẩn [2]
2.1.1 Giới thiệu bài toán
Một từ chuẩn loại M là một dãy các chữ số, mỗi chữ số nằm trong khoảng từ 1 đến M Số lượng các chữ số có mặt trong một từ được gọi là chiều dài của từ đó
Từ loại M được gọi là từ chuẩn nếu nó không chứa hai khúc (từ con) liền nhau mà giống nhau
Với giá trị n cho trước, hiển thị trên màn hình một từ chuẩn loại 3 có chiều dài n
Thí dụ:
12131 là từ chuẩn loại 3, chiều dài 5
1213123 là từ chuẩn loại 3, chiều dài 7
1213213 không phải là từ chuẩn vì nó chứa liên tiếp hai từ con giống
Trang 17Mảng v:
Với k = 5, tại vị trí v[5], từ v[1 5] = “12131” là từ chuẩn
Điều kiện P: v[1 k] là từ chuẩn
Điều kiện Q: Dừng thuật toán theo một trong hai tình huống sau đây:
nếu i = n thì bài toán có nghiệm v[1 n]
nếu i = 0 thì bài toán vô nghiệm
Duyệt các giá trị tại vị trí v[k] của từ v[1 k] bắt đầu từ v[k] + 1 đến
M (M = 3) sao cho v[1 k] là từ chuẩn
CoNuocDi = true nếu tồn tại 1 giá trị v[k] nhƣ vậy
Ngƣợc lại, nếu với mọi v[k] = v[k] + 1 đến M, từ v[1 k] đều không
chuẩn thì CoNuocDi = false
// Tai vi tri k xac dinh duoc 1 gia tri
// Xac dinh v[1 k] la tu chuan
bool Chuan(int k)
{
Trang 18Hàm Bang(k,d) kiểm tra xem hai từ kề nhau chiều dài d tính từ k trở
về trước có bằng nhau hay không
Hai từ được xem là khác nhau nếu chúng khác nhau tại một vị trí nào đó
Quá trình tìm kiếm lời giải của bài toán từ chuẩn theo thuật toán quay lui có thể mô tả bởi cây tìm kiếm lời giải sau:
Trang 19Hình 2.1 Cây tìm kiếm lời giải cho bài toán từ chuẩn
2.1.3 Nhận xét
Độ phức tạp của bài toán là hàm mũ MN
, tuy nhiên với bài toán tìm 1 nghiệm thì có thể giải trong thời gian tương đối nhanh
Với việc tổ chức dữ liệu sử dụng kiểu dữ liệu mảng có:
Ưu điểm: Truy nhập vào phần tử của mảng được thực hiện trực tiếp dựa vào địa chỉ tính được nên tốc độ nhanh, đồng đều đối với mọi phần tử
Nhược điểm: Kiểu dữ liệu mảng bị hạn chế về việc khai báo kích thước
Trang 202.2 Bài toán xếp hậu [1], [2]
2.2.1 Giới thiệu bài toán
Phát biểu bài toán:
Quân Hậu trên bàn cờ Vua có thể “ăn” quân khác theo hàng, theo cột chứa nó hoặc theo đường chéo của hình vuông nhận nó làm đỉnh
a) Tìm một cách xếp N quân Hậu trên bàn cờ Vua kích thước N N ô sao cho không quân nào “ăn” được quân nào
b) Tìm mọi cách xếp N quân Hậu theo điều kiện trên
Lịch sử bài toán:
Bài toán được đưa ra vào năm 1848 bởi kỳ thủ Max Bezzel, và sau đó nhiều nhà toán học, trong đó có Gauss và Georg Cantor, có các công trình về bài toán này và tổng quát nó thành bài toán xếp hậu
Các lời giải đầu tiên được đưa ra bởi Franz Nauck năm 1850 Nauck
cũng đã tổng quát bài toán thành bài toán n quân hậu
Năm 1874, S Gunther đưa ra phương pháp tìm lời giải bằng cách sử dụng định thức, và J.W.L Glaisher hoàn chỉnh phương pháp này Edsger Dijkstra đã sử dụng vấn đề này năm 1972 để minh họa sức mạnh của những
gì ông gọi là cấu trúc chương trình
Ông cũng mô tả chi tiết về thuật toán quay lui - theo chiều sâu Định lý: Với N > 3, có ít nhất một nghiệm cho bài toán N quân hậu Định lý này được chứng minh lần đầu bới Ahrens năm 1910
Sau đó Hoffman, Loessi, và Moore năm 1969
Gần đây có một số lời giải mới được công bố, thậm chí có phương án xếp được ngay 1 nghiệm của bài toán tại trang web:
http://vi.wikipedia.org/wiki/Bài_toán_tám_quân_hậu
Trang 21Các biến thể của bài toán:
Tìm số quân hậu tối thiểu mà có thể khống chế tất cả các ô trong bàn
cờ Bài toán 3-D N quân hậu:
Đặt N2
quân hậu trên khối lập phương kích thước N N N sao cho không có quân hậu nào “ăn” được quân nào Trong đó, mỗi hàng song song với trục tọa độ hoặc mỗi đường chéo chỉ có thể đặt 1 quân hậu
Bài toán 9 quân hậu (được mở rộng thành bài toán N + k queens): Cho một số nguyên dương N và một số nguyên không âm k, hãy đặt k quân tốt và N + k quân hậu trên một bàn cờ kích thước N dòng, N cột để giữa
2 quân hậu trên cùng một hàng, cột, hoặc đường chéo có ít nhất một quân tốt?
Bài toán m quân hậu, m quân mã trên bàn cờ N N
Với N là số nguyên tố, sẽ có nghiệm với cách giải riêng cho bài toán
2.2.2 Tổ chức dữ liệu và chương trình
Phương án 1 Sử dụng mảng 1 chiều
Sử dụng mảng 1 chiều x[1 n] lưu vị trí đặt các quân hậu
Phần tử x[i] của mảng x cho biết phải đặt Hậu thứ i tại cột i và dòng x[i]
Giả sử ta có 1 cách xếp hậu chính xác (không con hậu nào ăn nhau) thì tất cả N con hậu mỗi con phải nằm trên 1 hàng và 1 cột
Cách lưu bàn cờ như đã giới thiệu đảm bảo rằng tất cả N con hậu, mỗi con đứng trên 1 hàng và 1 cột riêng
Trang 22// Tim cach dat Hau i tren ban co nxn
//Xuat phat tu dong x[i+1]
//Tim dong moi co the dat duoc Hau i
int DatHau(int n, int i){
Điều kiện đặt được Hậu i trên dòng v của bàn cờ là nó không bị các Hậu
đã đặt trước đó, tức là các Hậu j = 1 (i - 1) chiếu (Tính chất P)
Hậu j < i chiếu (đụng độ) Hậu i khi và chỉ khi x[j] = x[i] (cùng dòng) hoặc i - j = abs(x[i] - x[j]) (Hậu i và Hậu j nằm trên hai đỉnh đối diện của hình
vuông, do đó hai cạnh liên tiếp của hình vuông này phải bằng nhau)
Hậu 3 và Hậu 1 nằm trên hai đỉnh đối diện của hình vuông
Hàm DatDuoc có chức năng kiểm tra xem Hậu i có đặt được trên dòng v trên bàn cờ.
// Dat duoc Hau i tai dong v tren ban co nxn
bool DatDuoc(int n, int i, int v){
int j;
Trang 23for(j = 1; j < i; ++j)
if(x[j] == v || i-j == abs(x[j]-v)) return 0;
return 1;
}
lại DatDuoc = false
Nếu Hậu i bị chiếu, ta dịch Hậu thứ i xuống dòng tiếp theo
Mỗi khi đặt được Hậu thứ i ta chuyển qua Hậu tiếp theo i + 1, ngược lại, lùi Hậu i ra ngoài bàn cờ, chuyển qua xét Hậu trước đó, Hậu i - 1
Trang 24Hình 2.3 Lời giải 2 với N = 4
Ở trạng thái xuất phát, trên dòng 1 có 4 lựa chọn cho quân hậu: quân hậu thứ nhất có thể đứng ở các cột 1,2,3,4
Nếu lựa chọn Ô (1,1), ở dòng thứ hai chỉ còn hai lựa chọn là cột 3 và cột 4
Nếu lựa chọn cột 3, trên dòng thứ 3 sẽ không còn ô nào không bị khống chế Ô (3,1) và (3,3) khống chế bởi (1,1), ô (3,2) và (3,4) khống chế bởi (2,4) Ta loại bỏ phương án chọn ô (2,3) này và xét tiếp phương án chọn ô (2,4)
Khi lựa chọn ô (2,4) ta cũng chỉ đặt thêm được một quân hậu ở dòng thứ ba Dòng thứ tư lại không thể đặt quân hậu nào
Do đó ta lùi lại dòng thứ nhất, xét khả năng tiếp theo (1,2), ta lần lượt được dãy các ô (1,2), (2,4), (3,1), (4,3)
Trang 25Tiếp tục với ô (1,3), (1,4) Chỉ có hai đường đi từ gốc tới lá với độ dài
4 nên bài toán 4 hậu chỉ có 2 lời giải thể hiện trên cây bằng các đường đi được
in đậm
Hình 2.4 Cây lời giải bài toán xếp hậu với N = 4
Phương án 2 Sử dụng kiểu dữ liệu bitset đánh dấu các đường chéo
Ta sử dụng thêm 2 mảng kiểu bitset để đánh dấu các đường chéo của các hậu đã đặt trên bàn cờ với ý nghĩa sau đây:
Mảng cheo1 kiểm soát các đường chéo theo hướng Tây Bắc -
Trang 26Mảng cheo2 kiểm soát các đường chéo theo hướng Đông Bắc - Tây
Nam Ta tạm gọi là các đường chéo phụ
Như vậy, Hậu k đặt tại vị trí dòng d cột c khi CheoOn(d,c) tức là
id1(d,c) và id2(d,c) đã bị kiểm soát
cheo1.test(id1(d,c)) || cheo2.test(id2(d,c))
Trang 27Ngược lại, id1(d,c) và id2(d,c) rỗi (không bị kiểm soát) khi
Hàm Find() có chức năng tìm vị trí đặt Hậu k trên bàn cờ, bằng cách dịch dần Hậu k xuống dưới
// Tim dong dat hau k
// dich dan Hau k xuong duoi
// Hau k dat tai dong d
// Khong dung voi cac hau 1 k-1 dat truoc
Trang 28Mỗi khi tìm vị trí đặt hậu thứ k trên bàn cờ ta cần kiểm tra xem hậu k
đó có đụng độ với tất cả (k-1) hậu đặt trước đó không Thời gian chi phí tập
trung ở chính điểm này
Trang 29Phương án 2 sử dụng kiểu dữ liệu bitset đánh dấu các đường chéo giúp nâng cao tốc độ tính toán khi kiểm tra hai hậu đụng độ nhau
Kiểu dữ liệu bitset có cấu trúc như mảng, nhưng mỗi phần tử chỉ chiếm
1 bit, tiết kiệm bộ nhớ, thao tác dễ dàng
2.3 Bài toán đa giác
2.3.1 Giới thiệu bài toán
Năm 1967, tác giả Franz Owen Armbruster đã đưa ra trò chơi có tên Instant Insanity [6] Trong vòng nhiều năm nó đã thu hút nhiều người chơi và trở nên rất phổ biến ở Mỹ
Trò chơi Instant Insanity bao gồm bốn khối lập phương với các mặt được tô màu với bốn màu sắc (đỏ, xanh dương, xanh lá cây và màu trắng)
Người chơi phải sắp xếp các khối trong một cột sao cho mỗi bên của cột (trước, sau, trái và bên phải) có màu của các khối không trùng nhau
Thí dụ:
Hình 2.3.1 chưa phải đáp án của bài toán vì:
Ở mặt trên của cột, khối 1 và khối 4 cùng có màu trắng: W
Ở mặt dưới của cột, khối 1 và khối 2 cùng có màu đỏ: R
Hình 2.8 Trò chơi Instant Insanity
Hình 2.9 Đáp án đạt được sau khi xoay mỗi khối sang trái 1 góc 90 o