Trong khi đó thuật toán quay lui là một thuật toán điển hình để giải lớp bài toán liệt kê hay bài toán tối ưu như: bài toán người giao hàng, bài toán con mã đi tuần, bài toán 8 hậu, bài
Trang 1ĐẠI HỌC ĐÀ NẴNG TRƯỜNG ĐẠI HỌC SƯ PHẠM
KHOA TIN
- -
PHẠM THỊ THANH HIỀN
NGHIÊN CỨU PHƯƠNG PHÁP QUAY LUI VÀ
ỨNG DỤNG GIẢI BÀI TOÁN SUDOKU
KHÓA LUẬN TỐT NGHIỆP
Trang 2Mục lục
MỞ ĐẦU 1
I LÝ DO CHỌN ĐỀ TÀI: 1
II MỤC TIÊU, NHIỆM VỤ: 2
III PHƯƠNG PHÁP NGHIÊN CỨU: 2
IV BỐ CỤC CỦA ĐỀ TÀI: 2
Chương I: CƠ SỞ LÝ THUYẾT 3
I CƠ SỞ LÝ THUYẾT: 3
1 Mảng: 3
1.1 Mô hình quan niệm: 3
1.2 Các đặc trưng cơ bản: 3
1.3 Cấu trúc lưu trữ: 3
1.4 Các phép toán cơ bản: 3
2 Hàm đệ quy: 4
2.1 Đệ quy là gì? 4
2.2 Cấu trúc chính của một chương trình đệ quy: 4
2.3 Đặc điểm: 5
2.4 Ví dụ: 5
3 Khử đệ quy: 6
3.1 Khái niệm: 7
3.2 Cách thực hiện : 7
II NGÔN NGỮ LẬP TRÌNH: 7
1 Vài nét về Visual C#: 7
2 Đặc điểm của ngôn ngữ C#: 8
Chương II: PHƯƠNG PHÁP QUAY LUI 10
Trang 3* Tư tưởng của thuật toán: 11
II MÔ HÌNH CỦA BÀI TOÁN: 11
III ỨNG DỤNG: 12
1 Phương pháp : 12
2 Giải thuật tổng quát : 13
Chương III: BÀI TOÁN SUDOKU 15
I GIỚI THIỆU BÀI TOÁN: 15
1 Lịch sử ra đời: 15
2 Luật chơi: 16
3 Các biến thể: 17
II XÂY DỰNG CẤU TRÚC DỮ LIỆU CHO BÀI TOÁN: 18
III THUẬT TOÁN: 23
1 Tổng quan: 23
1.1 Xác định bài toán: 23
1.1.1 Thông tin vào: 23
1.1.2 Thông tin ra: 23
1.2 Cách xác định mỗi ô số bất kỳ: 23
1.2.1 Xác định các ô theo số thứ tự từ 1 đến 81: 23
1.2.2 Xác định bằng [hàng, cột]: 24
1.2.3 Xác định bằng [vùng, số thứ tự trong vùng]: 24
2 Vấn đề đặt ra: 25
3 Giải quyết vấn đề: 26
3.1 Vấn đề 1: 26
3.2 Vấn đề 2: 30
4 Giải thuật chính: 31
5 Các phương thức sử dụng trong chương trình: 32
6 Xây dựng các hàm: 33
Trang 46.1 Hàm kiểm tra cột: 33
6.2 Hàm kiểm tra hàng: 34
6.3 Hàm kiểm tra vùng: 35
6.4 Hàm giải chương trình thủ công: 36
6.5 Hàm giải chương trình bằng phương pháp quay lui: 36
6.6 Hàm giải đến đáp án cần chọn: 38
6.7 Hàm đếm số đáp án: 38
IV GIỚI THIỆU CHƯƠNG TRÌNH GIẢI: 38
1 Tổng quan: 38
2 Chức năng chính: 43
3 Bảng phím tắt: 44
V THỬ NGHIỆM: 45
KẾT LUẬN 48
TÀI LIỆU THAM KHẢO 49
Trang 5MỞ ĐẦU
I LÝ DO CHỌN ĐỀ TÀI:
Ngày nay với sự phát triển không ngừng của khoa học kỹ thuật, đặc biệt trong các ngành mũi nhọn như: Điện Tử - Tin Học - Viễn Thông v.v Nếu chúng ta không thường xuyên cập nhật thông tin thì chúng ta không bắt kịp đà phát triển của thế giới Đất nước ngày càng tiến bộ, khoa học kĩ thuật ngày càng phát triển đòi hỏi con người ngày nay phải có năng lực thật sự, phải có khả năng tư duy logic tốt để tiếp cận với công nghệ hiện đại một cách nhanh chóng nhất Vấn đề đặt ra là làm sao để phát triển khả năng tư duy của con người, đôi khi chúng không nhận ra rằng chính những trò chơi trí tuệ, trò chơi với những con số có thể giúp chúng ta rèn luyện trí não, tư duy logic
Và SuDoKu là một trò chơi trí tuệ nổi tiếng, một trò chơi không ồn ào nhưng nó vẫn âm thầm phát triển bởi nó không đơn thuần là một trò chơi mà nó giúp kích thích tư duy, suy nghĩ logic của chúng ta thông qua những con số Ngoài những vấn
đề trên, SuDoKu hấp dẫn giới trẻ bởi một lý do nữa là có thể chơi được mọi lúc mọi nơi, có thể chơi trên xe buýt, trong giờ ra chơi, thậm chí khi đi dã ngoại, du lịch Luật chơi SuDoKu cực kỳ đơn giản, nhưng đáp án đôi khi lại cực kỳ khó giải, do không cần dùng đến kiến thức số học hay tính toán, SuDoKu thích ứng cho mọi người, trẻ em cũng có cơ hội giải được SuDoKu thành công như người lớn
Trong khi đó thuật toán quay lui là một thuật toán điển hình để giải lớp bài toán liệt kê hay bài toán tối ưu như: bài toán người giao hàng, bài toán con mã đi tuần, bài toán 8 hậu, bài toán tìm đường đi trong mê cung Bằng việc liệt kê các tình huống, thử các khả năng có thể cho đến khi tìm thấy một lời giải đúng, thuật toán quay lui chia nhỏ bài toán, lời giải của bài toán lớn sẽ là kết quả của việc tìm kiếm theo chiều sâu của tập hợp các bài toán phần tử
Trang 6Nhận thấy tư tưởng của thuật toán rất phù hợp với cách giải của trò chơi, nên đề
tài ”Nghiên cứu phương pháp quay lui và ứng dụng giải bài toán SuDoku” được
thực hiện nhằm tìm hiểu về thuật toán quay lui và ứng dụng của nó
II MỤC TIÊU, NHIỆM VỤ:
Đề tài này được thực hiện nhằm đạt được mục tiêu là hiểu rõ, hiểu sâu sắc hơn về thuật toán quay lui Xây dựng thành công chương trình giải SuDoKu với nhiều đáp án
và với một thời gian nhanh nhất
III PHƯƠNG PHÁP NGHIÊN CỨU:
- Tìm hiểu thông tin trên mạng internet, sách, báo, tạp chí…
- Thu thập ý kiến chuyên gia (giáo viên hướng dẫn, các giáo viên trong và ngoài khoa, ý kiến của bạn bè,…)
- Kết hợp nghiên cứu lý thuyết với thực hành, rèn luyện kỹ năng phân tích chương trình và kỹ năng lập trình
IV BỐ CỤC CỦA ĐỀ TÀI:
Nội dung của đề tài được trình bày như sau:
MỞ ĐẦU
Chương I: CƠ SỞ LÝ THUYẾT
Chương II: PHƯƠNG PHÁP QUAY LUI
Chương III: BÀI TOÁN SUDOKU
KẾT LUẬN
TÀI LIỆU THAM KHẢO
Trang 7Chương I: CƠ SỞ LÝ THUYẾT
I CƠ SỞ LÝ THUYẾT:
1 Mảng:
1.1 Mô hình quan niệm:
Mảng là một dãy có thứ tự (về mặt vị trí) các phần tử với hai đặc điểm sau :
- Cấu trúc lưu trữ đơn giản nhất là dùng địa chỉ được tính để thực hiện lưu trữ
và tìm kiếm các phần tử, là mảng một chiều hay vectơ
- Các phần tử được bố trí sát nhau trong bộ nhớ và theo thứ tự tăng dần của các
chỉ số nên dễ dàng tìm được địa chỉ của một phần tử bất kỳ nếu biết chỉ số
1.4 Các phép toán cơ bản:
- Thường chỉ có các phép tạo lập (create) mảng, tìm kiếm (retrieve) một phần tử
của mảng, cập nhật (update) một phần tử của mảng …Ngoài giá trị, một phần tử của
mảng còn được đặc trưng bởi chỉ số (index) thể hiện thứ tự của phần tử đó trong
mảng Vectơ là mảng một chiều, mỗi phần tử ai của nó ứng với một chỉ số i Ma trận
là mảng hai chiều, mỗi phần tử aij ứng với hai chỉ số i và j Tương tự người ta cũng
Trang 82 Hàm đệ quy:
2.1 Đệ quy là gì?
Ta nói:
- Một đối tượng là đệ quy nếu nó bao gồm chính nó như một bộ phận hoặc nó
được định nghĩa dưới dạng của chính nó
- Một thủ tục được gọi là đệ quy nếu trong quá trình thực hiện nó phải gọi đến
chính nó nhưng với kích thước nhỏ hơn của tham số
- Trong thân của một hàm, nếu nó gọi tới chính hàm đó để xử lý bài toán thì gọi
là hàm đệ quy.
Ví dụ:
1) Định nghĩa số tự nhiên:
- là một số tự nhiên
- n là số tự nhiên nếu n-1 là số tự nhiên
2) Định nghĩa hàm giai thừa:
- 0! = 1
- Nếu n > 0 thì n! = n(n-1)!
2.2 Cấu trúc chính của một chương trình đệ quy:
Một chương trình đệ quy về căn bản gồm 2 phần:
Trong đó, tác động cần được thực hiện cho giá trị hiện thời của các tham
số được định nghĩa bằng các tác động đã được định nghĩa trước đấy với kích thước nhỏ hơn của tham số
Ví dụ: if n>1 then gt:=n*gt(n-1);
Trang 9- Sử dụng đệ quy là một phương pháp làm cho chương trình ngắn gọn, dễ hiểu nhưng nó sẽ làm tốn bộ nhớ và thời gian
Ta có giá trị truyền vào hàm gt qua biến n
Trong ví dụ này, qui trình thực hiện như sau:
Trang 10- Mất nhiều thời gian xử lý, làm giảm tốc độ chạy chương trình.
- Không áp dụng cho mọi ngôn ngữ lập trình
Đệ quy không những là một phương pháp lập trình quan trọng mà còn là một phương pháp suy nghĩ để giải quyết vấn đề một cách tổng quát dựa trên ý tưởng:
+ Đơn giản hoá công việc + Phân vùng để xử lý
3 Khử đệ quy: Đệ quy là quả tim trong các nghiên cứu lý thuyết cũng như thực
hành tính toán, đã thể hiện rất nhiều sức mạnh và có ưu điểm trong nhiều bài toán Nhưng có đôi khi, sự hạn hẹp của bộ nhớ dành cho chương trình con không cho phép chúng ta làm điều đó.Vì vậy vấn đề khử đệ quy lại cần được quan tâm, xem xét
Trang 11bộ, khôi phục các biến và chuyển tới địa chỉ trả về
II NGÔN NGỮ LẬP TRÌNH:
1 Vài nét về Visual C#:
C# là một ngôn ngữ lập trình hướng đối tượng được phát triển bởi Microsoft, là phần đầu cho kế hoạch NET của họ Microsoft phát triển C# dựa trên C++ và Java C# được thiết kể bởi Anders Hejlsberg kiến trúc sư phần mềm nổi tiếng với các sản phẩm Turbo Pascal Và ông là người đứng đầu nhóm thiết kế Borland Delphi, một trong những thành công đầu tiên của việc xây dựng môi trường phát triển tích hợp (IDE) cho lập trình Client/Server
Trang 12C# cũng là ngôn ngữ lập trình điều khiển sự kiện, các chương trình được tạo ra sẽ
sử dụng IDE (Integrated Developmen Environment) Với IDE, người lập trình có thể tạo, chạy, kiểm tra và debug các chương trình C# Bên cạnh đó, nền NET cho phép các thành phần của một phần mềm được viết từ các ngôn ngữ lập trình khác nhau có thể tương tác được với nhau, thậm chí người phát triển ứng dụng có thể đóng gói các phần mềm cũ để nó hoạt động với chương trình C# mới
Giống như các ngôn ngữ lập trình khác, C# cũng hỗ trợ các kiểu dữ liệu cơ bản như integer, float, boolean, string, array và các câu lệnh điều khiển (if, while, for, switch, do…while…) Tuy nhiên, như đã trình bày ở trên, C# cũng có những đặc điểm riêng của nó
2 Đặc điểm của ngôn ngữ C#:
C#, theo một hướng nào đó, là ngôn ngữ lập trình phản ánh trực tiếp nhất đến NET Framework mà tất cả các chương trình NET chạy và nó phụ thuộc mạnh
mẽ vào Framework này
- Không có khái niệm biến toàn cục (global variables) và hàm (functions) Tất cả các hàm, phương thức trong một chương trình viết bằng ngôn ngữ C# đều được khai báo dưới dạng một lớp Mọi kiểu biến, kể cả các kiểu giá trị đơn giản đều
được xem như các đối tượng Tuy nhiên, ta có thể dùng thuộc tính static đối với các hàm và biến trong một lớp được khai báo public thay vì sử dụng biến toàn cục và
hàm
- C# yêu cầu rất chặt chẽ đối với kiểu Boolean (bool), các câu lệnh có điều kiện như while và if đều đòi hỏi biểu thức điều kiện phải có kiểu bool Nếu trong
C++ ta có phát biểu if(a) statement, biểu thức trong điều kiện if có thể được chuyển
thành giá trị kiểu bool, cho dù a có thể được khai báo kiểu int hay pointer, C# thì
khác, nó không có khái niệm “a nguyên là đúng hay sai” Điều này buộc người lập
trình phải sử dụng những biểu thức có kiểu trả về chính xác là bool Đặc tính này rất
Trang 13- C++ cho phép đa thừa kế (multiple interitances) và nếu được sử dụng đúng cách, đây thực sự là điểm rất mạnh Tuy nhiên, đa thừa kế rất khó quản lý và như vậy cũng rất khó áp dụng Đây là một trong những lý do C# chỉ phát triển thừa kế đơn (single inheritance)
- Namespaces trong C#: Khái niệm Namespaces được hiểu một cách đơn giản là tập các lớp có mối liên hệ lẫn nhau Ví dụ như ta gom các lớp có liên quan đến hoạt động của cơ sở dữ liệu lại và đặt cho chúng một không gian tên (namespace) chung gọi là DataActivity Vì C# không cho phép có hai lớp cùng tên trong cùng một chương trình, việc dùng namespace sẽ giúp ta tránh được những đụng độ trong vấn đề đặt tên Sẽ hoàn toàn có thể xảy ra sự đụng độ trên nếu chúng
ta có nhiều lớp được khai báo trong cùng một chương trình, chẳng hạn lớp Connection trong DataActivity sẽ xung đột với lớp Connection trong InternetActivity Để tránh sự đụng độ này, C# quy định tên lớp phải bao gồm namespace của lớp đó Vì thế tên thích hợp của 2 lớp Connection trong trường hợp trên là DataActivity Connection và InternetActivity.Connection Điểm nổi bật của C# Namespace là không ánh xạ một cách vật lý như đối với Java Các lớp với cùng một namespace có thể ở nhiều thư mục khác nhau Và namespace có thể bao gồm các lớp, các sự kiện, các exception và thậm chí là các namespace khác
Trang 14Chương II: PHƯƠNG PHÁP QUAY LUI
I KHÁI NIỆM QUAY LUI:
Kĩ thuật quay lui (backtracking) như tên gọi của nó, là một quá trình phân tích đi xuống và quay lui trở lại theo con đường đã đi qua Bằng việc liệt kê các tình huống, thử các khả năng có thể có cho đến khi tìm thấy một lời giải đúng, thuật toán quay lui chia nhỏ bài toán, lời giải của bài toán lớn sẽ là kết quả của việc tìm kiếm theo chiều sâu của các bài toán phần tử Trong suốt quá trình tìm kiếm nếu gặp phải một hướng nào đó mà biết chắc không thể tìm thấy đáp án thì quay lại bước trước đó và tìm hướng khác kế tiếp hướng vừa tìm đó Trong trường hợp không còn một hướng nào khác nữa thì thuật toán kết thúc
Thuật toán quay lui có thể được thể hiện theo sơ đồ cây tìm kiếm theo chiều sâu như hình dưới:
Trang 15Từ hình vẽ, dẽ dàng nhận thấy:
- Ở một bài toán hiện tại (mỗi nốt), ta đi tìm lời giải cho bài toán đó Ứng với
lời giải, ta đi giải bài toán kế tiếp cho đến khi bài toán gốc trở nên đầy đủ
- Lời giải của bài toán gốc thường là một lối đi từ gốc đến nốt cuối cùng
(không có nốt con)
* Tư tưởng của thuật toán:
- Nét đặc trưng của kĩ thuật quay lui là các bước hướng tới lời giải cuối cùng
của bài toán hoàn toàn được làm thử
- Tại mỗi bước, nếu có một lựa chọn được chấp nhận thì ghi nhận lại lựa chọn
này và tiến hành các bước thử tiếp theo Còn ngược lại không có lựa chọn nào thích
hợp thì làm lại bước trước, xóa bỏ sự ghi nhận và quay về chu trình thử các lựa
chọn còn lại
- Điểm quan trọng của thuật toán là phải ghi nhớ tại mỗi bước đi qua để tránh
trùng lặp khi quay lui Các thông tin này cần được lưu trữ vào một ngăn xếp-Stack
(vào sau ra trước), nên thuật toán thể hiện ý thiết kế một cách đệ quy
- Thuật toán quay lui thường được cài đặt theo lối đệ quy, mỗi lần gọi hàm đệ
quy, hàm đệ quy được truyền một tham số (trong các tham số) là chỉ số của bài toán
con, trong hàm sẽ cố gắng tìm lời giải cho bài toán con đó, nếu tìm thấy thì gọi hàm
đệ quy để giải bài toán con tiếp theo hoặc là đưa ra đáp án bài toán lớn nếu đã đầy
đủ lời giải, nếu không tìm thấy thì chương trình sẽ trở về điểm gọi hàm đó Mục
đích của việc sử dụng hàm đệ quy là để thuật toán được rỏ ràng, dễ viết, dễ hiểu hơn
và cũng để bảo toàn các biến, các trạng thái lúc giải bài toán con
II MÔ HÌNH CỦA BÀI TOÁN:
Lời giải của bài toán thường biểu diễn bằng một véc tơ gồm n thành phần phải thỏa mãn các điều kiện nào đó Để chỉ ra lời giải x, ta phải xây dựng dần các
thành phần lời giải x=(x1,x2, xn)
Trang 16Tại mỗi bước i:
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)
Trang 172 Giải thuật tổng quát :
Thuật toán quay lui có thể được mô tả bằng đoạn mã sau (thủ tục này thử cho x i
<Thử cho x[i] bằng giá trị v>
if <x[i] là phần tử cuối cùng trong cấu hình hoặc i=n>
<Thông báo cấu hình tìm được>
else
{
<Ghi nhận việc cho x[i] nhận giá trị v (nếu cần thiết)>
Try(i+1); // gọi đệ quy chọn tiếp x[i+1]
<Nếu cần thì bỏ ghi nhận việc thử x[i]=v để thử giá trị khác> }
}
}
(Thuật toán quay lui sẽ bắt đầu bằng lời gọi Try(1))
+ Đầu tiên, Try(int i) là hàm đệ quy quay lui trong đó i là biến chạy từ 1 n tương ứng với số thứ tự của x1, x2, x3, … , xn theo phương pháp đệ quy
+ Tiếp theo vòng lặp for cho các giá trị của từng phần tử x1, x2, x3,… Tất nhiên, đối với mỗi bài toán riêng thì những giá trị này là khác nhau
Trang 18+ Trạng thái cuối tức là điểm dừng của thuật toán này Thực chất thuật toán quay lui cũng là đệ quy nên việc xác định điểm dừng cực kỳ quan trọng và luôn luôn phải có
+ Tiếp theo là phần xuất ra, vì như đã thấy, khi if (phần tử cuối cùng trong cấu hình) thì đã xuất ra màn hình và không chạy bất kỳ hàm đệ quy nào nữa Tuy nhiên, khi xuất ra nó lại xuất tới nhiều dãy số (tùy từng bài tập) Lý do, nếu để ý thì chúng
ta sẽ thấy phía trên có 1 vòng for, nó sẽ hoạt động giống như kiểu nhiều vòng lặp for lồng nhau
for(i =1; i<=n; i++) for(j=1; i<n; i++)
…
for(z=1; z<n; z++) xuat()
Với m vòng for lồng nhau như vậy sẽ xuất ra n^m lần
Như vậy nếu không đặt điều kiện nào thì vòng for đầu tiên sẽ là m lần, tiếp theo trong mỗi lần đó lại có m lần for khác
Tóm lại, trong thủ tục mô tả trên, điều quan trọng nhất là đưa ra được một danh sách các khả năng đề cử và xác định được giá trị của biểu thức logic [ chấp nhận x[i] ] Dễ thấy rằng bài toán vô nghiệm khi ta đã duyệt hết mọi khả năng mà không
có khả năng nào thoả mãn yêu cầu Chú ý rằng là đến một lúc nào đó thuật toán 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 không thể lùi được nữa
Trang 19Chương III: BÀI TOÁN SUDOKU
I GIỚI THIỆU BÀI TOÁN:
1 Lịch sử ra đời:
Trò chơi này được kiến trúc sư Howard Garns ở New York thiết kế và được giới thiệu lần đầu tiên vào năm 1979 trên tạp chí Dell (Mỹ) với tên gọi là "Number Place" Tháng 4/1984, Number Place lần đầu tiên được giới thiệu tại Nhật trên báo Monthly Nikolist với tên gọi "Suuji wa dokusinh ni kagiru", dịch sang tiếng Anh có nghĩa là "những con số phải độc nhất" hoặc "những con số tìm thấy chỉ một lần" và được "rút gọn" thành SuDoKu (su = number, doku = single)
Nhưng trò chơi này chỉ trở nên phổ biến khi người Anh nhập cuộc Báo Times số ngày 12/11/2004 đã giới thiệu nó với tên gọi “SuDoKu” dựa trên kết quả phát triển chương trình trò chơi trên máy vi tính của một quan tòa về hưu người New Zealand sống ở Hongkong tên là Wayne Gould Sau đó, SuDoKu lần lượt xuất hiện trên hầu hết các tờ báo hàng đầu của Anh và được "đưa" đến Australia nhờ tập đoàn báo chí Telegarph
Từ ngày 2/8/2005, chương trình Radio Times của đài BBC (Anh) có một chuyên
đề hằng tuần về SuDoKu mang tên Super SuDoKu SuDoKu đã xuất hiện trên tivi lần đầu tiên vào ngày 1/7/2005 trong chương trình SuDoKu Live trên kênh Sky One Đây là một cuộc thi gồm 9 đội (mỗi đội 8 người cùng với một nhân vật nổi tiếng) tranh tài với nhau, tạo nên bảng SuDoKu lớn nhất thế giới (rộng 84 m với 1905 giải pháp đúng), câu đố được khắc trên một sườn đồi ở Chipping Sodbury nước Anh Hiện nay, SuDoKu đã có mặt trên các báo, tạp chí hàng đầu và trở thành trò chơi gây sốt tại hơn 40 quốc gia và vùng lãnh thổ trên thế giới, trong đó có Việt Nam SuDoKu xuất hiện tại Việt Nam sớm nhất là trên tạp chí Khám Phá (Trực thuộc
Sở Khoa học và Công nghệ Thành phố Hồ Chí Minh), sau đó đến Thanh Niên, Hoa Học Trò, được xem như là một hình thức giải trí đầy trí tuệ của giới trẻ Đặc biệt,
Trang 20mục Vua trò chơi trên báo Hoa Học Trò với "món chủ lực" là SuDoKu thu hút rất đông học sinh tham gia (theo kết quả công bố của báo)
2 Luật chơi: Quy luật của trò chơi tương đối đơn giãn.Cho một bàn hình vuông
được chia thành một lưới 81 ô nhỏ gồm 9 hàng và 9 cột, 81 ô nhỏ đó lại được chia thành 9 vùng, mỗi vùng có 9 ô Đề bài SuDoKu là một bàn hình vuông như thế, trên
đó tại một số ô người ta đã điền sẵn một số giá trị Cách chơi như sau:
Phải điền các số từ 1 đến 9 vào mỗi hàng dọc, ngang không được trùng lặp
Ở mỗi hàng dọc, mỗi hàng ngang và mỗi ô vuông 3*3 được phân cách rõ ràng ( bằng gạch đen đậm) luôn phải đảm bảo có đủ các số từ 1 đến 9
Ở mỗi hàng dọc, mỗi hàng ngang và mỗi ô vuông 3*3 được phân cách rõ ràng (bằng gạch đen đậm) các số chỉ được sử dụng một lần và không lặp lại
Ví dụ: Cho đề bài như sau, yêu cầu dùng các số từ 1 dến 9 để điền vào các ô còn lại
Trang 21Đáp án sẽ là:
3 Các biến thể:
Ngoài khuôn dạng chuẩn có kích thước 9x9 ô, chia làm 3x3 vùng, SuDoKu còn
có rất nhiều biến thể khác Một số biến thể phổ biến như:
- Kích thước 4x4 ô chia làm 2x2 vùng
- Kích thước 6x6 ô chia làm 2x3 vùng
- Kích thước 5x5 ô chia vùng theo pentomino (được phát hành với tên goi Logi-5)
- Kích thước 7x7 ô chia vùng theo heptomino
- Kích thước 8x8 ô chia vùng theo qui tắc (4x2):(4x2) Đây là cách chia thành
4 vùng chính, mỗi vùng 16 ô Trong mỗi vùng chính lại chia thành 2 vùng 8x8 dựa vào màu nền của từng ô Tuy theo cách bố trí các ô khác màu này, sẽ phát sinh thêm một biến thể con khác Cách bố trí đơn giản nhất là các ô khác màu nằm xen kẽ nhau – trông rất giống bàn cờ quốc tế (Game Sudoku do người Việt Phạm Văn Hải phát triển: Sudoku Plus 8x8)
Trang 22Biến thể với kích thước lớn hơn cũng khá phổ biến:
- Kích thước 16x16 ô (Monster SuDoKu)
- Kích thước 12x12 ô chia làm 4x3 vùng (Dodeka SuDoKu)
- Kích thước 25x25 ô (Giant SuDoKu)
Biến thể với kích thước lớn nhất được phổ biến là 100x100 ô
II XÂY DỰNG CẤU TRÚC DỮ LIỆU CHO BÀI TOÁN:
1 Một ô số SuDoKu bao gồm 9 miền con (hay còn gọi là 9 vùng), đặt theo thứ tự là
1, 2, 3, 4, 5, 6, 7, 8, 9 Chia thành 9 hàng và 9 cột như hình sau:
2 Dữ liệu sử dụng trong chương trình là dữ liệu kiểu mảng:
Cột
Hàng
Trang 23Trong đó giá trị row[i,j] nhận 2 giá trị quy ước là 0 và 1
row[i,j]=0 tức là hàng i không thể điền thêm giá trị j vào bất cứ ô nào nữa
vì giá trị j đã tồn tại trong hàng i
Ví dụ: Giả sử đề bài có hàng thứ 2 được cho như sau:
Khi đó row[2,2]=0, row[2,8]=0
row[i,j]=1 tức là hàng i có thể điền thêm giá trị j vào bất cứ ô nào chưa
được điền của hàng i
Ví dụ: Với ví dụ trên thì row[2,9]=1
- int [,] column=new int[10,10]; là mảng 2 chiều dùng để đánh dấu cột có thể
điền một số nào đó hay không
Trong đó column[i,j] nhận 2 giá trị là 0 và 1
column[i,j]=0 cột i không thể điền giá trị j vào
column[i,j]=1 cột i có thể điền giá trị j vào
Ví dụ: Đề bài có cột thứ 2 được cho như sau:
Khi đó column[2,2]=0 column[2,9]=1 Chỉ những giá trị chưa được điền trong cột mới có thể được điền vào Những giá trị đó sẽ có giá trị trả về là 1
Trang 24- int [,] area=new int[10,10]; tương tự như đối với mảng row[i,j] và column[i,j]
mảng area[i,j] cũng là mảng 2 chiều dùng để đánh dấu vùng có thể đánh một số
nào đó vào hay không area[i,j] cũng nhận 2 giá trị là 0 và 1 Nếu area[i,j]=0 thì vùng i không thể điền giá trị j vào Ngược lại nếu area[i,j]=1 thì vùng i có thể điền giá trị j vào
Ví dụ: Giả sử đề bài cho vùng thứ 2 có các giá trị sau:
- int [,] AREA=new int[10,10]; là mảng cố định, dùng để thiết lập giá trị mặc định của chỉ số vùng
Trong đó AREA[i,j] nhận các giá trị từ 1 đến 9
i: chỉ số hàng j: chỉ số cột
Giá trị trả về của AREA là chỉ số vùng
Khi đó area[2,7]=0 area[2,1]=0 Tức là vùng 2 chỉ được điền các giá trị chưa
có trong vùng đó và giá trị 1 là có thể điền được
Trang 25Ví dụ: AREA[4,5] sẽ trả về giá trị là 5 Tức là hàng 4 cột 5 là thuộc vùng 5
- int[, ,] agree = new int[10, 10, 11]; là mảng 3 chiều dùng để đánh dấu trên
từng ô trống một có bao nhiêu giá trị có thể điền được và đó là những giá trị nào Trong đó, giá trị agree[i,j,k] nhận các giá trị từ 1 đến 9
Trang 26Ví dụ: Giả sử đề bài cho vùng thứ 1 có các giá trị sau:
- int[,] value = new int[10,10]; là mảng 2 chiều dùng để chỉ giá trị đang được điền hiện tại tại một ô bất kì
Value=[i,j] nhận các giá trị từ 1 đến 9
Ví dụ: Với ví dụ trên, nếu value[1,1]=2 thì ô hàng1 cột 1 đang được đánh số
thứ 2 trong 5 khả năng được điền, tức là ô hàng 1 cột 1 đang được điền số 2
Với các cách đánh dấu này ta dễ dàng duyệt các khả năng điền số của một ô,
cho phép loại bỏ khả năng bất kỳ khi biết khả năng đó là không thuận lợi
Value[1,1]=5
Giả sử ô hàng 1 cột 1 nhận 7 giá trị là:
1, 2, 3, 4, 6, 8, 9 Khi đó agree[1,1,0]=7 và các giá trị đó là:
agree[1,1,1]=1 agree[1,1,2]=2 agree[1,1,3]=3 agree[1,1,4]=4 agree[1,1,5]=6 agree[1,1,4]=8 agree[1,1,5]=9
Tức là vùng 1 chỉ được điền các giá trị chưa có trong vùng đó và giá trị trả về là 1 nghĩa là có thể điền được