1. Trang chủ
  2. » Luận Văn - Báo Cáo

Đồ Án MÃ ĐI TUẦN ( KNIGHT’s TOUR )

20 3,8K 22
Tài liệu đã được kiểm tra trùng lặp

Đ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 20
Dung lượng 0,94 MB

Nội dung

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 những bài toán cụ thể.. Sau một thời gian học tập và nghiên cứ

Trang 1

Đồ án Cấu trúc dữ liệu và Giải thuật 2009 MÃ ĐI TUẦN

ĐẠI HỌC ĐÀ NẴNG TRƯỜNG ĐẠI HỌC BÁCH KHOA KHOA CÔNG NGHỆ THÔNG TIN

-

CẤU TRÚC DỮ LIỆU & GIẢI THUẬT

Đề tài 9 : MÃ ĐI TUẦN ( KNIGHT’s TOUR )

Giáo viên hướng dẫn : Phan Thanh Tao Sinh viên thực hiện : Mai Trần Trung Hiếu

Huỳnh Văn Vương

Nguyễn Văn Bình Huỳnh Khánh Nguyên

Lớp : 07T1 Nhóm : 12A

Trang 2

MỤC LỤC

MỤC LỤC 2

LỜI NÓI ĐẦU 3

I GIỚI THIỆU ĐỀ TÀI 4

II NGHIÊN CỨU LÝ THUYẾT 4

III MÔ TẢ BÀI TOÁN 5

IV XÂY DỰNG CẤU TRÚC DỮ LIỆU CHO BÀI TOÁN 5

V GIẢI PHÁP – THUẬT TOÁN ĐÃ CÓ ( ĐỆ QUY QUAY LUI ) 6

VI GIẢI PHÁP – THUẬT TOÁN ĐỀ XUẤT (WARNSDORFF) 6

VII LẬP TRÌNH VÀ THỬ NGHIỆM 7

VIII LỜI KẾT 10

IX CODE TOÀN BỘ CHƯƠNG TRÌNH “MÃ ĐI TUẦN” 11

TÀI LIỆU THAM KHẢO 20

Trang 3

LỜI NÓI ĐẦ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ắt cô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

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 những 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ế thuật toán, để nắm bắt những kiến

thức đã học một cách tốt hơn, nhóm chúng 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ù đã ra sức nghiên cứu và cố gắng nhưng chắc chắn khó tránh khỏi những thiếu sót, chúng em rất mong 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 chân thành đến thầy Phan Thanh Tao đã giúp chúng em

hoàn thành đề tài này

Nhóm sinh viên thực hiện.

Trang 4

I GIỚI THIỆU ĐỀ TÀI

“Mã đi tuần” (Knight’s Tour) là một bài toán

liên quan đến một quân mã trên một 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à

duy chuyển theo luật của 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 quân mã

được gọi là “Hành trình đóng” (Closed Tour) nếu vị trí

kết thúc của quân mã tấn công được vị trí xuất phát của

nó (để quân mã có thể đi tuần tiếp một vòng nữa ngay

lập tức) Nếu không thì được gọi là hành trình mở

Lập trình để giải quyết bài toán là một vấn đề phổ biến của các sinh viên thuộc các ngành

Khoa học Máy tính Những biến thể của bài toán “Mã đi tuần” bao gồm việc giải quyết bài

toán trên các kiểu bàn cờ khác kiểu 8*8 (n*n, hình chữ nhật,…) Ở phạm vi đồ án này, em chỉ

phát triển hành trình đóng của quân mã.

II NGHIÊN CỨU LÝ THUYẾT

Bài toán “Mã đi tuần” là một trong nhiều ví dụ

tổng quát của đường đi Hamilton trong lý thuyết đồ thị

Việc tìm hành trình đóng của con mã tương tự như việc

tìm hành trình đóng của chu trình Hamilton.

Các tài liệu tham khảo sớm nhất để giải quyết bài

toán xuất hiện từ thế kỷ thứ IX Nhưng giải thuật đầu

tiên đầy đủ cho bài toán về hành trình của quân mã là

“Giải thuật Warnsdorff” (Warnsdorff’s algorithm),

công bố lần đầu năm 1823 bởi H C Warnsdorff Thuật toán Warnsdorff được biết đến như là phương pháp Heuristic của “Mã đi tuần”.

Trên bàn cờ cỡ 8 * 8 có đúng 26,534,728,821,064 lời giải Và số cách giải là 9.862 đối

với bàn cờ cỡ 6 * 6 Không có lời giải hành trình đóng cho các bàn cờ có cỡ nhỏ hơn.

Trang 5

III MÔ TẢ BÀI TOÁN

1 Xác định thông tin vào (Input) :

- Một bảng vuông (bàn cờ) kích thước n*n.

- Tọa độ xuất phát của quân mã N(x,y).

2 Xác định thông tin ra (Output) :

- Một bảng vuông (bàn cờ) có đánh dấu vị trí theo

thứ tự từ 1 (vị trí xuất phát) đến n*n (vị trí kết

thúc) của quân mã.

- Từ vị trí thứ k sang vị trí thứ k+1 phải theo đúng

luật di chuyển quân mã trong cờ vua

3 Xác định vị trí di chuyển từ 2 đến n*n sao cho quân mã :

- Duy chuyển đúng luật.

- Mỗi ô chỉ được đi qua 1 lần.

- Vị trí cuối cùng (n*n) có thể nhảy tới vị trí xuất phát (1).

IV XÂY DỰNG CẤU TRÚC DỮ LIỆU CHO BÀI TOÁN

- Biểu diển bàn cờ bằng một ma trận K[n][n].

- Giá trị của mỗi ô K[i][j] (0 <= i,j < n) trên bàn cờ như sau :

• K[i][j] = 0 : Ô (i,j) chưa được quân mã đi qua.

• K[i][j] = t : Ô (i,j) được quân mã đi đến ở nước thứ t (1 <= t <= n*n).

- Cấu trúc dữ liệu cho mỗi bước đi của quân mã :

Nước đi có thể của con mã được phân tích như sau :

Trang 6

• Từ 1 vị trí (i,j) trên bàn cờ thì có tối đa 8 vị trí (u,v) khác nhau cho quân mã nhảy tới Việc thu được vị trí (u,v) từ (i,j) có thể được giải quyết bằng phương pháp cộng thêm độ chênh lệch về tọa độ chứa sẵn trong 2 mảng phụ hằng sau :

ver[ ] = {+2, -1, -1, -2, -2, +1, +1, +2};

hor[ ] = {-1, +2, -2, -1, +1, -2, +2, +1};

Ví dụ : Vị trí (u1,v1) = (i + ver[1], j + hor[1]) ,….

• Vị trí (u,v) cần tìm bị ràng buộc bởi 2 điều kiện :

Thứ 1, (u,v) phải còn nằm trong bàn cờ, tức là (0 <= u < n) và (0 <= v < n).

Thứ 2, K[u][v] phải bằng 0, tức là vị trí này chưa được quân mã đi qua

V GIẢI PHÁP – THUẬT TOÁN ĐÃ CÓ ( ĐỆ QUY QUAY LUI )

Thông thường, ta sẽ nghĩ đến thuật toán đệ quy quay lui để giải quyết bài toán “Mã đi

tuần” (phương pháp vét cạn) Ta sẽ xét đến những hạn chế còn mắc phải của phương pháp này

sau Thuật toán đệ quy quay lui như sau :

- Bắt đầu từ vị trí xuất phát (1).

- Từ vị trí thứ (k) ta đi tìm vị trí thứ (k+1).

- Sử dụng 2 mảng phụ để tìm các khả năng của vị trí thứ (k+1) Với mỗi khả năng (k+1) ta thực hiện :

• Nếu là vị trí thứ n*n và hành trình đóng thì có được kết quả.

• Nếu chưa là vị trí thứ n*n thì tiếp tục tìm vị trí thứ (k+2).

• Nếu hết đường đi tại vị trí thứ (k+1), tức là cả 8 khả năng đều bất khả thi thì quay lại, tìm theo hướng (k+1) khác.

Những hạn chế còn mắc phải của thuật toán đệ quy quay lui :

- Vì sử dụng vét cạn nên chỉ áp dụng được với những bài toán với bàn cờ có kích cỡ nhỏ.

- Trường hợp xấu nhất độ phức tạp của bài toán có thể là O(n64)

Để xử lý các hạn chế trên, ta xét thuật toán Warnsdorff sau :

Các thuật ngữ :

- Khanang[i][j] : Khả năng (số đỉnh) mà tại ví trí (i,j) có thể đi được.

- Uutien[ ] : Mảng sắp xếp độ ưu tiên của các khả năng.

Trang 7

Thuật toán Warnsdorff như sau :

Nhận thấy ở thuật toán đệ quy quay lui, hạn chế là do ta không phân biệt độ ưu tiên của

các hướng đi có thể có từ vị trí (i,j) Có tối đa 8 vị trí (u,v) mà từ (i,j) có thể nhảy tới, ta phải chọn ra hướng đi nào tốt nhất, dể nhất để hướng cho quân mã Ta xác định thứ tự ưu tiên của các (u,v) như sau :

- Ở mỗi vị trí (u,v) trên ta tính số Khanang[u][v] của nó.

- Sắp xếp số Khanang[u][v] của mỗi vị trí (u,v).

- Vị trí (u,v) có số Khanang[u][v] bé nhất là tốt nhất, ta đặt Uutien[0] là vị trí (u,v) đó,…

vị trí có Khanang[u][v] lớn nhất là ít được ưu tiên nhất.

Như vậy, từ vị trí thứ (i,j), quân mã sẽ nhảy lần lượt các đến (u,v) có độ ưu tiên đã sắp xếp.

1 Lập trình

Chương trình bài toán “Mã đi tuần” được viết bằng ngôn ngữ lập trình C.

Code và toàn bộ chương trình được đính kèm theo.

2 Kết quả thử nghiệm

Chạy File Con Ma Di Tuan.EXE ta được kết quả như sau :

Trang 8

Tiếp theo chương trình sẽ giới thiệu MENU như dưới đây :

Chúng ta chọn các chức năng của MENU, bao gồm :

- Chọn 1 để giải bài toán “Mã đi tuần”.

- Chọn 2 để xem đề tài.

- Chọn 3 để xem thông tin sinh viên thực hiện đồ án.

- Chọn 0 để thoát khỏi chương trình.

Chọn chức năng 2 :

Trang 9

Nhấn ENTER để quay trở lại MENU và chọn chức năng 1 :

Chương trình sẽ yêu cầu ta nhập Cỡ của Bàn Cờ Vua (6 hoặc 8), nhập tọa độ xuất phát

của quân mã (X,Y) Ví dụ dưới đây ta nhập size = 8, và (X,Y) = (7,3).

Và ta được kết quả Hành Trình đóng của quân mã như sau :

Tiếp tục nhấn ENTER để quay trở lại MENU , ta chọn chức năng 3 :

Thông tin nhóm sinh viên thực hiện :

Trang 10

Nhấn ENTER để quay về MENU và chọn chức năng 0 để thoát khỏi chương trình.

“Mã đi tuần” là một ví dụ điển hình về việc kết hợp giữa Giải thuật và Cấu trúc dữ

liệu để giải quyết bài toán

Phương pháp Đệ quy quay lui cho phép ta tìm được đường đi của quân mã chỉ bằng vài

dòng lệnh, nhưng bên cạnh đó độ phức tạp của đệ quy là khá lớn Nên đối với những cấu trúc có kích cỡ lớn, đồ sộ thì việc sử dụng Đệ quy tỏ ra chậm và chiếm dụng bộ nhớ Việc kết hợp đệ quy với những thuật toán thông minh để giải quyết nhanh một bài toán là một bước tiến trong

kỹ thuật lập trình

Thuật toán Warnsdorff được biết đến như là phương pháp Heuristic của “Mã đi tuần”

Giải thuật chọn ra và sắp xếp độ tối ưu (mức ưu tiên) của các con đường mà quân mã cần lựa

chọn Điều đó hướng đến việc tìm ra kết quả nhanh nhất, ít chiếm dụng bộ nhớ nhất và tất nhiên, độ phức tạp là ít nhất.

Qua quá trình nghiên cứu, thực hiện để hoàn thành đề tài này, nhóm chúng em đã thấy được tầm quan trọng, những ưu điểm mà Giải thuật mang lại Nếu nói : Cấu trúc dữ liệu là một con đường, thì Giải thuật có thể được ví như là phương tiện giao thông giúp ta duy chuyển nhanh trên con đường ấy Chúng em sẽ cố gắng để ngày càng hoàn thiện khả năng tư duy cũng như kỹ năng lập trình để ngày càng tiến bộ hơn trên lĩnh vực Công Nghệ thông tin.

Một lần nữa, em xin cảm ơn quý thầy cô đã giúp đỡ chúng em hoàn thành đề tài này.

Trang 11

IX CODE TOÀN BỘ CHƯƠNG TRÌNH “MÃ ĐI TUẦN”

#include<conio.h>

#include<stdio.h>

#include<dos.h>

/* Knight Tour */

const int maxx = 100;

int size,STOP=0;

int K[maxx][maxx], Khanang[maxx][maxx],d,c;

int TieptheoD[8], TieptheoC[8];

int ver[] = {+2, -1, -1, -2, -2, +1, +1, +2};

int hor[] = {-1, +2, -2, -1, +1, -2, +2, +1};

int row, col,times;

// -Ham khoi tao hanh trinh (hanh trinh all = 0);

void Khoitao() ;

// -Ham Kiem tra buoc tiep theo ok ko?

-int CHECK( -int row, -int col );

// -Ham In Ket

qua -void PRINT() ;

// -Ham kiem tra come back Vitri xuat phat

-int QUAYLAI( -int x, -int y) ;

// -Ham hoan doi 2 gia

tri -void SWAP(int &a, int &b) ;

// -Ham xet so buoc co the di cua 1

dinh -void KHANANG(int i,int j) ;

// -Thuat toan Warnsdorff : Xep do uu tien cac buoc

di -void WARNSDORFF(int row, int col, int &step, int Uutien[8] ) ;

// -Ham nhay ca tung ca tung :))

-void Knight (int times, int row, int col) ;

// CAC HAM TRANG TRI

-void tenten() ;

void tenten2() ;

void menu() ;

void loading() ;

void Demo() ;

void Detai() ;

void Infor() ;

void main()

{

clrscr();

float kt=0;

loading();

textbackground(BLUE);

clrscr();

do {

menu();

do {

gotoxy(15,23); delline() ;

Trang 12

textcolor(10);

cprintf("Press 0-3 to solve the questions: ") ;

scanf("%f",&kt); } while(kt!=0&&kt!=1&&kt!=2&&kt!=3);

switch (int(kt))

{

case 1 : Demo() ; getch() ; break;

case 2 : Detai() ; getch() ; break;

case 3 : Infor() ; getch(); break;

}

clrscr();

} while(kt!=0) ;

}

// -CAC HAM

CON -// -Ham khao tao hanh trinh(Lam = 0 ma tran K[])

void Khoitao()

{

int i,j;

for(i=0;i<size;i++)

for(j=0;j<size;j++) K[i][j]=0;

}

// -Ham kiem tra dinh co ok hay

ko? -int CHECK( ko? -int row, ko? -int col )

{

if ( row > size-1 || row < 0 || col > size-1 || col < 0 || K[row][col] !=

0 )

return 0;

else return 1;

}

// -Ham In Ket

qua -void PRINT()

{

int i,j,l;

textcolor(10);

l=K[d][c]-1;

gotoxy(15,3); cprintf("HANH TRINH CUA CON MA") ;

textcolor(WHITE);

gotoxy(7,5) ; cprintf("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");

gotoxy(7,7) ; cprintf("ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ");

textcolor(12);

gotoxy(4,6) ; cprintf(" ");

for(i=0;i<size;i++)

{ gotoxy(i*4+8,6); if(i==c) cprintf("%4d",i);

else printf("%4d",i); } for(i=0;i<size;i++)

{

gotoxy(4,i*2+8);

{if(i==d) cprintf("%2d ³",i); else printf("%2d ³",i);}

for (j=0;j<size;j++ )

if(K[i][j]>l) { gotoxy(j*4+8,i*2+8); cprintf("%4d", K[i][j] -l ); }

Trang 13

else { gotoxy(j*4+8,i*2+8); cprintf("%4d", size*size+K[i][j]-l ); } }

gotoxy(7,size*2+8); printf( "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄMTTHÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ" ); }

// Ham kiem tra come back Vitri xuat phat

-int QUAYLAI( -int x, -int y)

{

int i,u,v;

for(i=0;i<8;i++)

{

u=x+ver[i] ;

v=y+hor[i] ;

if((u<8&&u>-1)&&(v<8&&v>-1)) if((K[u][v]==1)) return 1;

}

return 0;

}

// -Ham hoan doi 2 gia

tri -void SWAP(int &a, int &b)

{

a = a + b;

b = a - b;

a = a - b;

}

// -Ham xet so buoc co the di cua 1

dinh -void KHANANG(int i,int j)

{

int k,u,v;

Khanang[i][j] = 0;

for ( k = 0; k < size; k++)

{

u = i + ver[k];

v= j + hor[k];

if ( CHECK(u,v) ) Khanang[i][j]++;

}

}

// -Thuat toan WARNSDORFF : Xep do uu tien cac buoc

di -void WARNSDORFF(int row, int col, int &step, int Uutien[8] )

{

int u,v,i,j;

int Cot1, Cot2;

int Dong1, Dong2;

step = 0;

for ( i = 0; i < 8; i++)

{

u = row + ver[i];

v = col + hor[i];

if ( CHECK(u,v) )

{ TieptheoD[step] = u;

TieptheoC[step] = v;

Trang 14

Uutien[step] = step; /* Luu lai trang thai cua Row va Col

*/

step++;

} }

/* SO SANH CHON RA BUOC NHAY TOI UU NHAT */

for(i= 0;i<step;i++)

{

for(j=i+1;j<step;j++)

{

Dong1 = TieptheoD[Uutien[i]];

Cot1 = TieptheoC[Uutien[i]];

Dong2 = TieptheoD[Uutien[j]];

Cot2 = TieptheoC[Uutien[j]];

KHANANG(Dong1,Cot1);

KHANANG(Dong2,Cot2);

if (Khanang[Dong1][Cot1] > Khanang[Dong2][Cot2])

SWAP(Uutien[i], Uutien[j]);

}

}

}

// -Ham nhay ca tung ca tung :))

-void Knight (int times, int row, int col)

{

int Uutien[8];

int step = 0,i;

int next_row, next_col;

if(!K[row][col])

{

K[row][col] = times ;

if(times==(size*size)) { if(QUAYLAI(row,col)) {PRINT() ; getch; STOP+ +;} }

else {

WARNSDORFF(row, col, step, Uutien);

for ( i = 0; i < step; i++)

{

if(STOP) break;

next_col = TieptheoC[Uutien[i]];

next_row = TieptheoD[Uutien[i]];

if (CHECK(next_row, next_col ))

Knight ( times + 1, next_row, next_col);

} }

K[row][col]=0;

}

}

// CAC HAM TRANG TRI

void Demo()

{

clrscr();

int i=10;

textcolor(10) ;

do{

gotoxy(15,7); delline();

Trang 15

cprintf("Nhap size cua ban co vua (6||8): ");

scanf("%d",&size); } while(size!=6&&size!=8);

Khoitao();

gotoxy(15,9); delline();

cprintf("Nhap vi tri xuat phat:");

do{

gotoxy(18,11); delline();

cprintf("Toa do X (0 <= X <= %d) :",size-1);

scanf("%d",&d); } while(d>size-1||d<0);

do{

gotoxy(18,13); delline();

cprintf("Toa do Y (0 <= Y <= %d) :",size-1);

scanf("%d",&c); }while(c>size-1||c<0);

gotoxy(15,17); cprintf("Press Enter to continue ");

textcolor(15);

gotoxy(15,15); cprintf("Ban da nhap Toa Do (%d,%d)",d,c);

gotoxy(43,17);

getch();

clrscr();

STOP=0;

Knight (1, 4, 3);

tenten();

}

// -Ham

Menu -void menu()

{

int i=12;

textcolor(WHITE);

gotoxy(i,2);

cprintf("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»");

gotoxy(i,3); cprintf("º º");

gotoxy(i,4); cprintf("º º");

gotoxy(i,5); cprintf("º º");

gotoxy(i,6);

cprintf("ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹");

gotoxy(i,7); cprintf("º º");

gotoxy(i,8); cprintf("º º");

gotoxy(i,9); cprintf("º º");

gotoxy(i,10);

cprintf("ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ");

gotoxy(i,11); cprintf("º º");

gotoxy(i,12); cprintf("º º");

gotoxy(i,13); cprintf("º º");

gotoxy(i,14);

cprintf("ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ");

gotoxy(i,15); cprintf("º

Ngày đăng: 10/04/2015, 16:30

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w