Mục đích của đề Đề tài “ Mã đi tuần ” nhằm mục đích: Giúp bản thân chúng em có thể hiểu rõ hơn, sâu hơn về các giải thuật và lựa chọn cấu trúc dữ liệu để giải quyết một bài toán Tin học
Trang 1Đề tài 39: Bài toán Mã Đi Tuần
Knight’s Tour
Trang 2LỜI MỞ ĐẦU Ngày nay, Tin học ngày càng phát triển nhanh chóng và được ứng
dụng rộng rãi trong mọi lĩnh vực của đời sống xã hội, việc học và nắm bắtcông nghệ mới đặc biệt là công nghệ thông tin ngày càng trở nên bức thiết.Đối với sinh viên trong ngành càng trở nên bức thiết Đối với sinh viên trongngành càng phải tích cực học tập, nắm vững mọi kiến thức về công nghệthông tin, trong đó cấu trúc dữ liệu và giải thuật được xem là cơ sở, nền tảngđầu tiên
Cấu trúc dữ liệu giúp cho sinh viên hiểu được tầm quan trọng của giải
thuật và cách tổ chức cấu trúc dữ liệu để giải quyết bài toán cụ thể
Sau một thời gian học tập và nghiên cứu ngôn ngữ lập trình C (C Programming Language), môn Cấu trúc dữ liệu, Phân tích thiết kế giải
thuật, để nắm bắt những kiến thức đã học một cách tốt hơn, nhóm bọn em đã thực hiện đề tài: “Mã Đi Tuần” (Knight’s Tour).
Trong quá trình thực hiện đề tài, mặc dù đã chăm chỉ nghiên cứu và tìmhiểu,song chắc chắn khó tránh khỏi những thiếu sót,vì vậy, chúng em rấtmong nhận được những sự chỉ dẫn, ý kiến đóng góp của quý thầy cô để chúng
em ngày càng hoàn thiện hơn Đồng thời chúng em xin gửi lời cảm ơn sâu sắc
và chân thành đến cô Lê Thị Mỹ Hạnh đã giúp chúng em hoàn thành đề tài
này
Nhóm sinh viên thực hiện
Trang 3MỤC LỤC
LỜI MỞ ĐẦU 2
MỤC LỤC 3
DANH MỤC HÌNH VẼ 5
Hình 1 Vị trí quân cờ khi bắt đầu 5
1 GIỚI THIỆU ĐỀ TÀI 6
1.1 Tên đề tài 6
2 CƠ SỞ LÝ THUYẾT 7
2.1 Ý tưởng 7
2.2 Cơ sở lý thuyết 8
3 TỔ CHỨC CẤU TRÚC DỮ LIỆU VÀ THUẬT TOÁN 9
3.1 Phát biểu bài toán 9
Xác định đầu vào (Input): 9
3.2 Cấu trúc dữ liệu 9
3.3 Thuật toán 12
4 CHƯƠNG TRÌNH VÀ KẾT QUẢ 14
4.1 Tổ chức chương trình 14
4.2 Ngôn ngữ cài đặt 22
4.3 Thực hiện chương trình 23
5 KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN 40
5.1 Kết luận 40
5.2 Hướng phát triển: 40
TÀI LIỆU THAM KHẢO 41
[1] Giáo trình toán rời rạc – Phan Thanh Tao – Đại học Bách Khoa – Đại học Đà Nẵng 41
[2] https://vi.wikipedia.org/wiki/Bài_toán_mã_đi_tuần 41
[3] Giải thuật và lập trình – Lê Minh Hoàng 41
[4] Phân tích thiết kế giải thuật – Phạm Nguyên Khang, Đỗ Thanh Nghị 41
Trang 5DANH MỤC HÌNH VẼ
Hình 1 Vị trí quân cờ khi bắt đầu
Hình 2 Cách đi của con mã
Hình 3 Thay đổi của con mã khi di chuyển
Hình 4 Mô tả các đỉnh trên bàn cờ 4*4
Trang 61 GIỚI THIỆU ĐỀ TÀI
1.1 Tên đề tài
ĐỀ TÀI 39: Bài toán Mã Đi Tuần: Con mã xuất phát từ một vị trí bất
kỳ trên bàn cờ vua, đi qua tất cả các vị trí trên bàn cờ, cuối cùng trở về vị trí xuất phát
Bài toán “ MÃ ĐI TUẦN” ( Knight’s Tour) là một bài toán liên quan tới
một quân mã trên bàn cờ vua Quân mã được đặt tại một vị trí trống bất kỳ trên bàn cờ và di chuyển theo luật cờ vua Nó nhảy qua mỗi ô trên bàn cờ
chính xác một lần Hành trình của con mã được gọi là “Hành trình đóng”
(Closed Tour) nếu vị trí kết thúc của con mã có thể đi được về vị trí xuất phát của nó ( để quân mã có thể đi tiếp một vòng nữa liền ngay sau đó) Nếu khôngthì được gọi là “ Hành trình mở”
1.2 Lý do lựa chọn đề tài
Bài toán mã đi tuần là một bài toán thú vị,
tương đối kinh điển, có nhiều hướng giải quyết, vì
vậy nhóm em đã chọn đề tài “ MÃ ĐI TUẦN ” này
làm đề tài cho môn học của mình
1.3 Mục đích của đề
Đề tài “ Mã đi tuần ” nhằm mục đích: Giúp bản thân chúng em có thể
hiểu rõ hơn, sâu hơn về các giải thuật và lựa chọn cấu trúc dữ liệu để giải quyết một bài toán Tin học, từ đó nâng cao khả năng tự học, rèn luyện kỹ năng lập trình của bản thân
Trang 72 CƠ SỞ LÝ THUYẾT
2.1. Ý tưởng
Giới thiệu bàn cờ: Theo Wikipedia có lẽ cờ vua xuất hiện vào khoảng
thế kỉ thứ 6 và phát triển trở thành môn trò chơi được nhiều người biết đến như hiện nay.Trò chơi diễn ra trên bàn cờ hình vuông có 8 hàng (đánh số từ 1 tới 8) và 8 cột (đánh chữ từ a tới h) tạo thành một bàn cờ có 64 ô vuông với 2 màu đen trắng xen kẽ Mỗi người bắt đầu với 16 quân cờ gồm 1 vua, 1 hậu, 2
mã, 2 tượng, 2 xe và 8 tốt được sắp xếp theo quy luật của bàn cờ Vị trí a và h
là vị trí của 2 con xe, b và g là vị trí 2 con mã, c và f là vị trí 2 con tượng, d là
vị trí con hậu, e là vị trí con vua, còn hàng liền trên là vị trí của 8 con tốt
(hình 1)
Hình 1 Vị trí quân cờ khi bắt đầuTrong bàn cờ vua, con mã là quân cờ có nước đi phức tạp nhất Mã đi theo hình chữ L Tiến hoặc lùi 2 ô sau đó sang trái hoặc phải 1 ô Qua trái hoặc phải 2 ô sau đó tiến hoặc lùi 1 ô Mã có thể di chuyển tới một trong các ô
có vòng tròn đỏ như hình 2
Trang 8Hình 2 Cách đi của con mã
Ý tưởng thực hiện: Ta cho quân mã xuất phát tại một ô bất kỳ trên bàn
cờ, cho quân mã đi đến các ô mà quân mã chưa hề đi qua, nếu tại một vị trí đi nào đó không tìm được nước đi thì lùi quân mã về vị trí trước đó và tiếp tục đihướng khác, cho đến khi quân mã thỏa mãn điều kiện bài toán
2.2. Cơ sở lý thuyết
Bài toán “ Mã đi tuần ” là một dạng của bài toán tổng quát hơn là bài
toán toán tìm đường đi Hamiton trong Lý thuyết đồ thị [1] Bài toán tìm hành trình đóng của quân mã là bài toán cụ thể của bài toán tìm chu trình
Hamiltonian.
Đồ thị: Là một cấu trúc rời rạc gồm các đỉnh và cạnh nối các đỉnh đó.
Đường đi Hamilton: Đường đi qua tất cả các đỉnh của đồ thị, mỗi đỉnh duy
nhất một lần
Chu trình Hamilton: Chu trình đi qua tất cả các đỉnh của đồ thị, mỗi đỉnh
duy nhất một lần
Trang 9Để hiểu rõ hơn về Lý thuyết đồ thị và chu trình Hamilton có thể tìm đọc cuốn sách “ Toán rời rạc ” ở mục tài liệu tham khảo.
Có nhiều thuật toán có thể áp dụng để tìm kiềm đường đi Hamilton như quy hoạch động, thuật toán ngẫu nhiên, Heuristic, quay lui,…
Tuy nhiên, trong báo cáo này, chúng em sẽ áp dụng thuật toán quay lui
để tìm lời giải cho bài toán “ Mã đi tuần”.
3 TỔ CHỨC CẤU TRÚC DỮ LIỆU VÀ THUẬT TOÁN
3.1 Phát biểu bài toán
Xác định đầu vào (Input):
- Một bàn cờ có kích thước n*n (với n là số nguyên dương)
- Tọa độ xuất phát của quân mã
+ Cấu trúc dữ liệu mảng một chiều b[n]:
Ta coi bàn cờ n*n như một đồ thị vô hướng và thừa nhận ô (i,j) của bàn
cờ là đỉnh (i-1) *n+j của đồ thị Với i,j chạy từ 1-> 8
Ví dụ ô (1,n) là đỉnh thứ (1-1)*n +n = n của đồ thị Như vậy việc tìmhành trình con mã để đi hết các ô của bàn cờ <=> tìm ra một hành trình đi hếtcác đỉnh của đồ thị, mỗi đỉnh quả một lần
+ Việc kiểm tra từ đỉnh u tới đỉnh v hay không ta có thể thấy như sau :
Trang 10Giả sử tọa độ (x1,y1) có đỉnh ở đồ thị là u -> (x1-1)*n + y1 = u.
Dễ thấy nếu (u % n =0) thì x1= u /n, y1=n, còn nếu (u % n != 0) thì x1= u/n +1, y1= u%n
Giả sử tọa độ (x2, y2) có đỉnh ở đồ thị là v -> (x2-1)*n + y2 = v
Dễ thấy nếu (v % n = 0) thì x2 = v /n, y2 = n , còn nếu (v % n != 0) thìx2= v/n + 1, y2= v%n
Ví dụ theo cách tính ở trên tọa độ (2,2) sẽ có đỉnh là 6 Có thể theo dõiHình 4
y(1,4)
1 2 3 4
5 6 7 8
Từ đó ta có thể kiểm tra từ u có đến v được hay không dựa vào việc so sánhgiá trị |x1-x2| * |y1-y2| với giá trị 2,nếu giá trị đó bằng 2 thì quân mã có thể dichuyển từ u → v,và ngược lại
Trang 11Sử dụng mảng b[n] để xác định trạng thái ô thứ i ( i từ 1 -> n*n ).
- Quy ước :
- b[i] = 0 : ô thứ i chưa được đi qua
- b[i] = k : ô thứ i đã được đi qua và là bước đi thứ k củaquân mã (1<= k <= 2^n)
+ Cấu trúc dữ liệu mảng hai chiều a[n][n]
Xem mỗi ô trên bàn cờ có tọa độ (x,y) với x, y (1->n), ta sử dụng một mảng 2chiều a[n][n] để biểu diễn tọa độ các ô
- Quy ước:
-a[x][y]=0: ô (x, y) là vị trí con mã chưa đi qua-a[x][y]=k: là vị trí con mã đã đi qua bước thứ k (1<= k <= 2^n)-a[x][y]=1: ô (x, y) là vị trí con mã bắt đầu xuất phát
-Dùng mảng dx[8], cy[8] để lưu trữ sai biệt về tọa độ khi quân mã dychuyển qua các ô trên bàn cờ
-Tại vị trí bất kỳ của con mã trên bàn cờ:
• Khi con mã lùi 2 dòng, lùi 1 cột thì tương ứng dx[]= -2, cy[]= -1
• Khi con mã lùi 1 dòng, lùi 2 cột thì tương ứng dx[]= -1, cy[]= -2
•Tương tự với các vị trí khác trong bàn cờ
=> Ta thu được 2 mảng như sau:
int dx[]={-1,-2,-2,-1,1,2,2,1};
int cy[]={2,1,-1,-2,-2,-1,1,2};
Trang 12y ( 1 -> n)
x ( 1 -> n)
Hình 4 Thay đổi khi con mã di chuyển
3.3 Thuật toán
Thuật toán đệ quy quay lui:
Tư tưởng chính của thuật toán: Tại mỗi bước cho quân mã thử tất cả
các bước đi kế tiếp Với mỗi bước đi, kiểm tra xem nếu nước đi hợp lệ
(chưa đi qua và ở trong bàn cờ) thì thử đi nước này Nếu quân mã đi qua hết bàn cờ thì xuất kết quả Ngược lại thì gọi đệ quy tiếp cho vị trí mới thửtrên Mỗi vị trí đã đi qua được đánh dấu bằng chính thứ tự nước đi trên bàn
cờ Sau khi không thử vị trí này thì phải bỏ đánh dấu để chọn giải pháp khác (trường hợp quay lui)
Trang 13+ Mã giả áp dụng thuật toán quay lui trên cấu trúc dữ liệu mảng một chiều b[n].
Void madituan()
{
For( v=1;v<=n;v++){
If(thỏa mãn là nước đi kế)
Ghi nhận nước đi;
If( là nước đi cuối và có thể về vị trí xuất phát)
Trang 14Đánh dấu nước đi;
If ( là nước đi cuối và có thể trở về vtri xuất phát)Ghi nhan kq;
Else{
Madituan();
Xoavtri;
}}}
}
4 CHƯƠNG TRÌNH VÀ KẾT QUẢ
4.1 Tổ chức chương trình
Source code:
+ Chương trình sử dụng cấu trúc dữ liệu mảng một chiều và phương
pháp đệ quy quay lui
Trang 16int kt(int u,int v)
Trang 17b[v]=count;
if(count==n*n&&(kt(X,v)==1)){
Trang 18b[v]=0;
}}
Trang 19+Chương trình sử dụng cấu trúc mảng hai chiều và phương pháp đệ quy quay lui:
Trang 20for(int j=0;j<n;j++)fprintf(f,"%5d",a[i][j]);
Trang 21&&c+cy[i]>=0&&c+cy[i]<n)t=1;
a[u][v]=k;
if(k==n*n&&check(u,v)==1){dem++;in();ghifile2();goto next;}
else{
next :madituan(u,v,k+1);
Trang 22}}
Trang 234.3 Thực hiện chương trình
4.3.1 Kết quả sau khi chạy chương trình
Sau khi biên dịch và chạy chương trình chúng em có bảng sau:
Kết quả thời gian (giây) thực hiện chương trình với bàn cờ kích thước 6*6
(với x là thời gian đợi thực hiện chương trình quá lâu)
Dựa vào bảng kết quả trên ta có nhận xét:
Sau khi cài đặt và chạy chương trình chúng em nhận thấy chương trình trả về kết quả đúng thỏa mãn hành trình đóng của quân mã với thời gian ngắn (<0.2 giây), nhưng khi cho kích thước của bàn cờ lớn từ 8*8 trở lên thời gian thực hiện chương trình rất lâu, có thể xem như không tìm được hành trình Đểgiải quyết vấn đề này chúng em đã tìm và nghiên cứu phương pháp duyệt ưu tiên Warndorff như một cách để giảm thời gian thực hiện chương trình
Phương pháp duyệt ưu tiên Warndorff : nếu gọi k là số ô kề với ô x và chưa đi qua (kề ở đây theo nghĩa đĩnh kề chứ không phải ô kề cạnh) thì từ một
ô ta sẻ không thử xét lần lượt hướng đi có thể, mà ta sẻ ưu tiên thử hướng đi tới ô có k nhỏ nhất trước
Trang 244.3.2 Áp dụng phương pháp duyệt ưu tiên Warndorff
+ Mã giả áp dụng duyệt ưu tiên vào chương trình sử dụng cấu trúc
dữ liệu mảng 1 chiều b[] – phương pháp quay lui
Int dembac(int u)
{
For(v từ 1 -> n*n){
If(thỏa mã là nước đi kế) tăng biến đếm lên 1;
}Trả về biến đếm;
If(thỏa mãn là nước đi kế và temp>dembac())Temp= dembac();
}Trả về biến temp;
}
Trang 25Void madituan()
{
For(v=1;v<=n;v++){
If(thỏa mãn là nước đi kế và dembac() bằng bacnhonhat())
Ghi nhận nước đi;
If(là nước đi cuối và có thể về vị trí xuất phát)
+ Mã giả áp dụng duyệt ưu tiên vào chương trình sử dụng cấu trúc
dữ liệu mảng 2 chiều a[][]- phương pháp quay lui
Sử dụng mảng p[] với mục đích lưu lại số nước đi có thể có của nước
đi tiếp theo từ vị trí hiện tại
Void toiuu(int d,int c)
{
Khai báo 2 biến dt,ct ;For(i từ 1->8)
{
Trang 26If(thỏa mãn là nước đi kế){
Lưu lại tọa độ dòng cột hiện tại tương ứng dt,ct;
For (j từ 1-8){
If(thỏa mãn là nước đi kế tiếp)Tăng biến đếm lên 1;
}Lưu biến đếm vào mảng p[];
}}
Sapxep() ;}
Void sapxep()
{
For(i từ 0- > 6)For(j từ i+1 -> 7){
If(p[i] > p[j]){
Sắp xếp lại 2 mảng dx[],dy[] từng cặp tương ứng, theo chiều tăng dần của mảng p[];
Trang 27If(chưa đi qua và trong bàn cờ){
Đánh dấu nước đi;
If(là nước đi cuối và có thể trở về vtri xuất phát)Ghi nhan kq;
Else{
Madituan();
Xoavtri;
}}}
}
Source code:
Trang 28+ Chương trình sử dụng cấu trúc dữ liệu mảng một chiều phương pháp đệ quy quay lui kết hợp duyệt ưu tiên.
Trang 31b[v]=count;
if(count==n*n&&(kt(X,v)==1)){
Trang 32{next :madituan(v);
count ;
b[v]=0;
}}
Trang 33+ Chương trình sử dụng cấu trúc dữ liệu mảng hai chiều phương pháp đệ quy quay lui kết hợp duyệt ưu tiên:
Trang 34for(int i=0;i<n;i++){
for(int j=0;j<n;j++)fprintf(f,"%5d",a[i][j]);
Trang 36if(demt==0)p[i]=9;
}}
Trang 37if(k==n*n&&check(u,v)==1){dem++;in2();ghifile2();goto next;}
else{
next :madituan4(u,v,k+1);
a[u][v]=0;
}}
Trang 39Thời gian (giây) thực hiện chương trình trên một số bàn cờ kích thước khác nhau khi kết hợp với phương pháp duyệt ưu tiên
CTDL – GT
Tọa độ
Mảng một chiều đệ quy quay lui + duyệt ưu tiên
Mảng hai chiều đệ quy quay lui + duyệt ưu tiên
Dựa vào bảng trên chúng em đưa ra một số nhận xét sau:
+ Khi chương trình trả về kết quả, thì kết quả đó chắc chắn thỏa mãn bài toán mã đi tuần hành trình đóng
+ Khi chưa áp dụng phương pháp duyệt ưu tiên để lựa chọn các nước đi thì chỉ giải quyết được bài toán với kích thước bàn cờ nhỏ (<= 6*6)
+ Áp dụng phương pháp duyệt ưu tiên giải quyết được bài toán với bàn
cờ 8*8,10*10,12*12 14*14 16*16
Trang 40+ Thời gian tìm được hành trình tùy thuộc vào tọa độ đỉnh xuất phát, với việc sử dụng cấu trúc dữ liệu khác nhau cũng ảnh hưởng đến thời gian cũng như kết quả tìm được hành trình.
+ Với một số tọa độ đỉnh xuất phát ví dụ: bàn cờ 14*14 tọa độ (12,1) chương trình sẻ rơi vào trạng thái chờ thực hiện rất lâu, khi đó xem như
không tìm được hành trình
+ Giải bài toán với cấu trúc dữ liệu mảng 1 chiều-giải thuật đệ qui quay lui tỏ ra vượt trội hơn so với cấu trúc dữ liệu mảng 2 chiều đệ quy quay lui về
số lượng tọa độ có thể tìm được đường đi ở tất cả vị trí xuất phát trên bàn cờ,
ví dụ: với bàn cờ 8*8 vị trí có tọa độ (1,1) (1,2), (1,8) thì bài toán sử dụng mảng 2 chiều-đệ quy quay lui không tìm đường đi nhưng ngược lại với cấu trúc dữ liệu mảng 1 chiều-giải thuật đệ qui quay lui thì tìm đươc hành trình
5 KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN
5.1 Kết luận
Bài báo cáo của chúng em đã cố gắng tổng hợp đầy đủ những nội dung
cơ bản liên quan đến đề tài ” Mã đi tuần” mà nhóm đã thực hiện Tuy
nhiên,chúng em rất mong nhận được sự đóng góp ý kiến của quý thầy cô và các bạn để bài báo cáo càng hoàn thiện hơn
5.2 Hướng phát triển:
- Biến thành trò chơi hai người theo ý tưởng này
Trang 41TÀI LIỆU THAM KHẢO
[1] Giáo trình toán rời rạc – Phan Thanh Tao – Đại học Bách Khoa– Đại học Đà Nẵng
[2] https://vi.wikipedia.org/wiki/Bài_toán_mã_đi_tuần
[3] Giải thuật và lập trình – Lê Minh Hoàng
[4] Phân tích thiết kế giải thuật – Phạm Nguyên Khang, Đỗ Thanh Nghị