1. Trang chủ
  2. » Công Nghệ Thông Tin

ĐỒ ÁN GIẢI THUẬT LẬP TRÌNH

41 470 3

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 41
Dung lượng 752 KB

Nội dung

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 2

LỜ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 3

MỤ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 5

DANH 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 6

1 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 7

2 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 8

Hì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 10

Giả 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 11

Sử 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 12

y ( 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 16

int kt(int u,int v)

Trang 17

b[v]=count;

if(count==n*n&&(kt(X,v)==1)){

Trang 18

b[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 20

for(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 23

4.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 24

4.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 25

Void 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 26

If(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 27

If(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 31

b[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 34

for(int i=0;i<n;i++){

for(int j=0;j<n;j++)fprintf(f,"%5d",a[i][j]);

Trang 36

if(demt==0)p[i]=9;

}}

Trang 37

if(k==n*n&&check(u,v)==1){dem++;in2();ghifile2();goto next;}

else{

next :madituan4(u,v,k+1);

a[u][v]=0;

}}

Trang 39

Thờ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 41

TÀ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ị

Ngày đăng: 19/01/2018, 11:58

TỪ KHÓA LIÊN QUAN

w