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

Đồ Án Mê cung và đường đi

20 3,1K 18

Đ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 190,5 KB

Nội dung

Nội dung báo cáo chia ra 5 phần Phần 1 : Cơ sở lý thuyết Phần 2 : Mô tả bài toán Phần 3 : Thuật toán Phần 4 : Chương trình Phần 5 : Kết quả & đánh giá Nhóm đã cố gắng hết sức để hoàn chỉ

Trang 1

Mở đầu

ấu trúc dữ liệu là môn học quan trọng mấu chốt trong chuyên ngành Công nghệ thông tin Nó là cơ sơ để chúng ta giải quyết một số bài toán đồng thời cung cấp những hiểu biết về cách tổ chức dữ liệu nhằm giải quyết các bài toán hiệu quả nhất

C

Đề tài của nhóm là : mê cung và đường đi Nội dung báo cáo chia ra 5 phần Phần 1 : Cơ sở lý thuyết

Phần 2 : Mô tả bài toán

Phần 3 : Thuật toán

Phần 4 : Chương trình

Phần 5 : Kết quả & đánh giá

Nhóm đã cố gắng hết sức để hoàn chỉnh đồ án, song chắc chắn không tránh khỏi thiếu sót, vì vậy kính mong nhận được góp ý và hướng dẫn của thầy cô cùng các bạn

Nhân dịp này, nhóm xin chân thành cám ơn các giảng viên khoa Công Nghệ

Thông Tin và đặc biệt là thầy Phan Thanh Tao đã hướng dẫn, giúp đỡ nhóm hoàn

thành Đồ án này

Nhóm báo cáo : C15

Nguyễn Xuân Thạch : 07T3

Đà Nẵng 27-11-2009

Mục lục

Trang 2

Mê cung: 3

Thuật toán Loang : 3

Cấu trúc hàng đợi: 4

PHẦN 2: MÔ TẢ BÀI TOÁN 5

Yêu cầu bài toán: 5

Cấu trúc lưu trữ dữ liệu và các hàm chính: 6

PHẦN 3: THUẬT TOÁN 7

Thuật toán tìm đường đi (ngắn nhất): 7

Thuật toán tìm tất cả các đường đi: 8

PHẦN 4: CHƯƠNG TRÌNH 9

PHẦN 5: KẾT QUẢ & ĐÁNH GIÁ 17

Hướng dẫn sử dụng chương trình 17

Đánh giá 19

Giới thiệu đề tài

Đề tài : Cho một mê cung (maze) và tìm đường đi trong mê cung

Trang 3

PHẦN 1: CÁC CƠ SỞ LÝ THUYẾT

Mê cung:

Là một hệ thống các con đường hoặc lòng hang động Được xây dựng nên bởi các hàng rào được bố trí theo quy luật nào đó

Các thành phần của mê cung:

Ô tường

Ô có thể đi

Ô bắt đầu, kết thúc

Tính chất: có duy nhất 1 lối vào và 1 lối ra Đường đi từ lối vào đến lối ra rất phức tạp Ứng dụng : Xây dựng các mật đạo, các mê cung giải trí trong công viên, trò chơi điện

tử

Thuật toán Loang :

Là thuật toán duyệt theo chiều rộng để tìm ra kết quả mà chúng ta mong muốn,

tư tưởng của thuật toán rất đơn giản : khi cho 1 bài toán chúng ta sẽ được cung cấp 1

số dữ kiện ban đầu và phải đưa ra kết quả mà bài yêu cầu(có thể có hoặc không), phương pháp này đưa ra với mục đích duyệt mọi khả năng có thể có của bài toán và nếu trong các khả năng đó có cấu hình mong muốn thì chúng ta coi như tìm được đáp

án và ngược lại là không có kết quả (no solution)

Trang 4

Để giải quyết dễ dàng người ta mô hình hóa bài toán về mô hình 1 đồ thị để làm việc

Giả sử dữ liệu ban đầu là gốc (root) của cây thì các khả năng sẽ là các lá, và trình tự giải bài toán sẽ là đường đi từ root đến lá (nếu lá đó là cấu hình mong muốn) quá trình Loang là quá trình kiểm tra tất cả các đường đi từ gốc đến tất cả các lá nếu tìm được đường đi đưa ra đáp án mà bài yêu cầu thì bài toán coi như giải xong

Cấu trúc hàng đợi:

Hàng đợi (tiếng Anh: queue) là một cấu trúc dữ liệu dùng để chứa các đối tượng làm việc theo cơ chế FIFO (viết tắc từ tiếng Anh: First In First Out), nghĩa là việc thêm vào hoặc lấy một đối tượng ra khỏi hàng đợi, được thực hiện theo cơ chế

"vào trước ra trước"

Trong hàng đợi, các đối tượng có thể được thêm vào hàng đợi bất kỳ lúc nào, nhưng chỉ có đối tượng thêm vào đầu tiên mới được phép lấy ra khỏi hàng đợi Thao tác thêm vào và lấy một đối tượng ra khỏi hàng đợi được gọi lần lượt là "enqueue" và

"dequeue" Việc thêm một đối tượng luôn diễn ra ở cuối hàng đợi và một phần tử luôn được lấy ra từ đầu hàng đợi

Trang 5

Cấu trúc dữ liệu hàng đợi có thể định nghĩa như sau: Hàng đợi là một cấu trúc

dữ liệu tương tự như ngăn xếp, hàng đợi hỗ trợ các thao tác:

 EnQueue(o): thêm đối tượng o vào cuối hàng đợi.

 DeQueue(): lấy đối tượng ở đầu queue ra khỏi hàng đợi và trả về giá trị của nó.

Nếu hàng đợi rỗng thì lỗi sẽ xảy ra

Các thao tác thêm, trích và huỷ một phần tử phải được thực hiện ở hai phía khác nhau của hàng đợi, do đó hoạt động của hàng đợi được thực hiện theo cơ chế FIFO Cũng như ngăn xếp, cấu trúc mảng một chiều hoặc cấu trúc danh sách liên kết

có thể dùng để biểu diễn cấu trúc hàng đợi

Khi mô hình bài toán về đồ thị để làm việc thì việc quan trọng hàng đầu là phải xác định được cấu trúc (struct) của định và quan hệ giữa các đỉnh khi xác định xong thì chúng ta tiến hành Loang bình thường, khi đó cấu trúc phần tử (element) của Queue chính là cấu trúc của đỉnh

Trong tin học, cấu trúc dữ liệu hàng đợi có nhiều ứng dụng: khử đệ qui, tổ chức lưu vết các quá trình tìm kiếm theo chiều rộng và quay lui, vét cạn, tổ chức quản lý và phân phối tiến trình trong các hệ điều hành,

PHẦN 2: MÔ TẢ BÀI TOÁN

Yêu cầu bài toán:

Với một mê cung cho trước, hãy tìm đường đi trong mê cung Ta cụ thể bài toán như sau:

Biểu diễn mê cung bằng ma trận 2 chiều với các giá trị 1 là tường , 0 là đường

đi Ta nhập vào ma trận và xuất ra đường đi tương ứng với ma trận mê cung đó

1 Thông tin vào :

a Ma trận mê cung

b Toạ độ vào, toạ độ ra

c Hình minh hoạ

Trang 6

1 0 1 1 1 1 1 1 1 1

1 0 1 0 0 0 0 0 0 1

1 0 0 0 1 1 0 1 1 1

1 1 0 0 0 1 0 0 0 1

1 1 0 1 0 0 1 1 0 1

1 0 0 1 1 0 1 1 0 1

1 1 0 1 0 0 0 0 0 1

1 1 0 0 0 1 1 1 0 1

1 0 0 1 0 0 0 0 0 1

1 1 1 1 1 1 1 1 0 1

2 Thông tin ra

a Đường ngắn nhất để thoát khỏi mê cung

b Tất cả các đường có thể thoát khỏi mê cung

c Hình minh hoạ

Cấu trúc lưu trữ dữ liệu và các hàm chính:

Để giải quyết bài toán đã cho, ta dùng cấu trúc hàng đợi Cấu trúc được mô tả bằng đoạn mã sau( trong ngôn ngữ C++) :

typedef struct tagDNode

{

int x;

int y;

struct tagDNode* next;

struct tagDNode* father;

}DNODE;

Hình minh hoạ

Trang 7

typedef struct tagDList

{

DNODE* pHead;

DNODE* pTail;

}QUEUE;

Hinh minh hoạ

Các nguyên mẫu hàm và công dụng của nó

 DNODE* GetNode(int u,int v); //khởi tạo 1 phần tử kiểu tagDNode và giá trị

trả về là con //trỏ kiểu DNODE để quản lý nó

 void EnQueue(QUEUE &l,DNODE* newe); //Thêm 1 phần tử newe vào

hàng đợi l

 DNODE* DeQueue(QUEUE &l); //Lấy 1 phần tử ra khỏi hàng đợi ( theo cơ

chế vào trước /ra trước )

PHẦN 3: THUẬT TOÁN

Thuật toán tìm đường đi (ngắn nhất):

QUEUE maze;

DNODE* p, g;

Bước 1:

Nạp đỉnh vào vào hàng đợi

Bước 2 :

While(maze.pHead != NULL)// Lặp trong khi hàng đợi chưa rỗng

{

- p=DeQueue(maze)// Lấy 1 đỉnh từ hàng đợi để xét

Trang 8

- Kiểm tra đỉnh đó là đỉnh ra ?

o Nếu đúng :In kết quả, kết thúc thuật toán

o Nếu sai :

 Kiểm tra các hướng có thể đi từ đỉnh đó ? ( cụ thể là trái phải trên dưới)

o g=GetNode(xnew,ynew);

o EnQueue(maze,g);// Nạp đỉnh mới vào hàng đợi

o g->father=p;// Đánh dấu đỉnh dẫn tới g }

Nếu kết thúc vòng lặp mà vẫn chưa có kết quả thì thông báo vô nghiệm

Thuật toán tìm tất cả các đường đi:

DNODE* S, Sw; //S là stack chứa các phần tử chứa đỉnh tạo thành đường đi

//Sw là stack chứa các đỉnh tạm thời

//S là stack chứa các đỉnh tạo thành đường đi

Bước 1:

Nạp đỉnh vào vào stack S

Bước 2:

Xét đỉnh đầu tiên ở S

- Nếu có đường đi từ đỉnh đó

{

Nạp tất cả đỉnh g đi được vào Sw;

Đánh dấu tất cả g->father=S;

Nạp đỉnh đầu của Sw vào S;

Xoá đỉnh đầu tiên của Sw;

Lặp lại bước 2:

}

- Nếu như không thể đi được nữa (bị tắt đường)

{

Nếu như Sw = NULL thì kết thúc Nếu không

{

Xoá lùi các đỉnh trong S cho tới vị trí Sw->father;// nghĩa là tại đỉnh mà ở đó có ngã rẽ

Nạp đỉnh đầu của Sw vào S;

Xoá đỉnh đầu của Sw;

Lặp lại bước 2:

Trang 9

} }

- Nếu đỉnh hiện tại là đỉnh ra

{

Xuất kết quả (nghĩa là xuất các đỉnh trong S);

Nếu Sw = NULL thì kết thúc Nếu không

{

Xoá lùi trong S tới vị trí Sw->father;

Nạp đỉnh đầu của Sw vào S;

Xoá đỉnh đầu của Sw;

Lặp lại bước 2:

} }

PHẦN 4: CHƯƠNG TRÌNH

Vì chương trình được viết bằng ngôn ngữ Visual C++ bao gồm nhiều thư viện tạo form, dialog nên chúng ta chỉ trình bày đoạn chương trình C++ trong môi trường Borland C

#include<stdio.h>

#include<conio.h>

#include<stdlib.h>

int MAZE[20][20]; // mang luu ma tran chinh

int MAZE2[20][20]; // mang luu ma tran phu

int hang,cot,xstart,ystart,xgoal,ygoal;

int leftDraw, topDraw; // toa do bat dau ve me cung

int coutWay;

typedef struct tagDNode

{

int x;

int y;

struct tagDNode* next;

struct tagDNode* father;

}DNODE;

typedef struct tagDList//tagDList la cau truc gom 2 con tro DNODE

//con tro DNODE co cau truc tagDNode

{

Trang 10

DNODE* pHead;

DNODE* pTail;

}QUEUE;

DNODE* GetNode(int u,int v)//Ham khoi tao,kieu tra ve la con tro DNODE tro den //1 phan tu tagDNode[DNODE]

{

DNODE *p;//p la con tro tro den DNODE

p=new DNODE;

if(p==NULL)

{

printf("Het bo nho");

exit(1);

}

//Gan thong tin cho p;

p->x=u;

p->y=v;

p->next=NULL;

p->father=NULL;

return p;

}

void AddFirst(QUEUE &l,DNODE* new_ele)//new_ele la con tro

{

if(l.pHead==NULL)//Xau rong

{

l.pHead=new_ele;

l.pTail=l.pHead;

}

else

{

new_ele->next=l.pHead;

l.pHead=new_ele;

}

}

void AddLast(QUEUE &l,DNODE* newe)//Right!!

{

if(l.pHead==NULL)//xau rong~

{

l.pHead=newe;

Trang 11

}

else

{

l.pTail->next=newe;

l.pTail=newe;

}

}

DNODE* RemoveFirst(QUEUE &l)//lay ra phan tu dau tien,ko xoa !

{

DNODE *p;

p=NULL;

if(l.pHead!=NULL)//xau ko rong~

{

p=l.pHead;

l.pHead=l.pHead->next;

if(l.pHead==NULL) l.pTail=NULL;

}

return p;

}

int check(int x,int y)

{

if(x<0||y<0) return 0;

if(x>=hang||y>=cot) return 0;

if(MAZE2[x][y]==0) return 1;

else return 0;

}

//////////////////////////////////////////////////////////////////////////

//Khoi Tao Tim All Way

FILE* fp;

int demA;

void WriteFile(DNODE* l)

{

DNODE* p;

p=l;

//fp=fopen("ketqua.txt","a+");

fprintf(fp,"%d ",demA);

Trang 12

{

fprintf(fp,"%d %d ",p->x,p->y);

p=p->next;

}

fprintf(fp,"\n\n");

}

void DisplayStack(DNODE* l)//Right!!

{

DNODE* p;

p=l;

printf("\n");

while(p!=NULL)

{

printf("%d%d-",p->x,p->y);

p=p->next;demA++;

}

printf("\n");

}

void SetFree(DNODE* &l,DNODE* vitri)//Right!!!

{

DNODE* p;int x,y;//Ham se xoa tu "Dinh Stack" den "vitri" cho truoc

if(l==NULL) return;

else

{

while(1) {

if(l==vitri) return;

p=l;

l=l->next;

x=p->x;y=p->y;MAZE2[x][y]=0;

delete p;

} }

}

void AddS(DNODE* &l,DNODE* new_ele)//Right!!!

{

int x,y;

new_ele->next=l;

Trang 13

x=new_ele->x;y=new_ele->y;

MAZE2[x][y]=100;//chu y khi add vao "duong di" thi khong cho di wa nua,dah dau 100

}

void AddSw(DNODE* &l,DNODE* new_ele)//Right!!!

{

new_ele->next=l;

l=new_ele; //Ham nay chi add vao Stack wait nen ko can thiet danh dau 100

void DelSw(DNODE* &l)//Right!!!

{

l=l->next; //Thuc chat ham DelSw chi la dich con tro Stack den ptu tiep theo

//Khong xoa,vi "Stack dau" can de Add vao "duong di" }

void DelS(DNODE* &l)

{

DNODE* p;int x,y;

if(l!=NULL){

p=l;

x=p->x;y=p->y;MAZE2[x][y]=0;

l=l->next;

delete p;

}

void AllWay(int daux,int dauy,int duoix,int duoiy)

{

DNODE* S,*p,*g,*Sw;

int x,y,beAdd;

S=NULL;

Sw=NULL;

// -TIM ALL

WAY -while(1)

{

x=S->x;y=S->y;//printf("\n%d:%d",x,y);

if(x==duoix&&y==duoiy)//Neu ve dich {

Trang 14

demA=0;

if(Sw==NULL) break; //Thuat toan se dung khi ko con ptu trong

het //duong roi

SetFree(S,Sw->father);//neu chua het duog, tiep tuc Add //"Stack wait"

//tro,nen moi thay doi

//Sw,nen can dich Sw trc

else {

beAdd=0;//Bien BeAdd dung de danh dau xem dinh hien tai co bi //tat

if(check(x,y+1)==1)//duong hay khong,neu co the di duoc thi dua

p=GetNode(x,y+1);p->father=S;AddSw(Sw,p);

beAdd=1;

} if(check(x,y-1)==1) {

p=GetNode(x,y-1);p->father=S;AddSw(Sw,p);

beAdd=1;

} if(check(x-1,y)==1) {

p=GetNode(x-1,y);p->father=S;AddSw(Sw,p);

beAdd=1;

} if(check(x+1,y)==1) {

p=GetNode(x+1,y);p->father=S;AddSw(Sw,p);

beAdd=1;

}

ta //add

Trang 15

{ //Stack wait -> Stack Way

g=Sw;DelSw(Sw);

AddS(S,g);

}

cac //duong di

ptu //nam trong

if(Sw==NULL) break;//Stack Wait else

{

SetFree(S,Sw->father);

g=Sw;DelSw(Sw);

AddS(S,g);

} }

}//end else }//end while

fclose(fp);

// -}

void GanMT()

{

int i,j;

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

for(j=0;j<cot;j++) MAZE2[i][j]=MAZE[i][j];

}

//////////////////////////////////////////////////////////////////////////

void main()

{

FILE *f;

f=fopen("maze1.txt","r");

fscanf(f,"%d",&hang);

fscanf(f,"%d",&cot);

fscanf(f,"%d",&xstart);

fscanf(f,"%d",&ystart);

fscanf(f,"%d",&xgoal);

fscanf(f,"%d",&ygoal);

Trang 16

for(int i=0;i<hang;i++)

for(int j=0;j<cot;j++) fscanf(f,"%d",&MAZE[i][j]);

fclose(f);

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

for(int j=0;j<cot;j++)

printf("%3d",MAZE[i][j]);

printf("\n");

}

GanMT();

//////////////////////////////////////////////////////////////////////////

//Tim Duong Ngan Nhat

int tempx,tempy;

DNODE *p,*g;

QUEUE Q;

Q.pHead=Q.pTail=NULL;

p=GetNode(xgoal,ygoal); // Duyet nguoc tu dich den diem bat dau

// de dua vao DSLK se in ra dung thu tu AddLast(Q,p);

while(Q.pHead!=NULL )

{

p=RemoveFirst(Q);

tempx=p->x;

tempy=p->y;

if(tempx==xstart&&tempy==ystart) {

g=p;

break;

}

if(check(tempx-1,tempy)==1){

g=GetNode(tempx-1,tempy);

g->father=p;

AddLast(Q,g);

MAZE2[tempx-1][tempy]=100;

} if(check(tempx+1,tempy)==1) {g=GetNode(tempx+1,tempy);g->father=p;

AddLast(Q,g);MAZE2[tempx+1][tempy]=100;}

Trang 17

if(check(tempx,tempy-1)==1) {g=GetNode(tempx,tempy-1);g->father=p;

AddLast(Q,g);MAZE2[tempx][tempy-1]=100;}

if(check(tempx,tempy+1)==1) {g=GetNode(tempx,tempy+1);g->father=p;

AddLast(Q,g);MAZE2[tempx][tempy+1]=100;}

}

if(MAZE2[xstart][ystart]==0) // Neu khong den duoc Diem Start -> ko co //duong

{

printf("Can't find a path from Start to Goal!");

}

else{

//ve duong -int dem=0;

int i,j;

printf("\nDuong Di Ngan Nhat:\n");

while(g!=NULL) // se duyet luon NODE dau tien

i=g->x;

j=g->y;

printf("%d:%d ",i,j);

g=g->father;

} }

//////////////////////////////////////////////////////////////////////////

//Tim Tat Ca Cac Duong

GanMT();

printf("\nTat Ca Cac Duong Di:\n");

AllWay(xstart,ystart,xgoal,ygoal);

}

PHẦN 5: KẾT QUẢ & ĐÁNH GIÁ

Hướng dẫn sử dụng chương trình

Giống như các chương trình phổ biến trên window, ta click vào file exe chương trình có giao diện đơn giản như sau:

Trang 18

Mở file dữ liệu mê cung có sẵn và ta được mê cung vẽ bằng các ô vuông như sau với tường là màu đỏ, vàng là đường đi và màu xanh là đỉnh vào và ra

Click chọn menu Best Path, chương trình sẽ vẽ ra đường đi ngắn nhất và liệt kê

số bước đi

Trang 19

Sau khi Click vào menu All Path, sẽ có hộp thoại nhắc ta Click vào menu View (hoặc phím Enter) để xem lần lượt các đường đi

Đánh giá

Vì dùng thuật toán tìm kiếm theo chiều rộng cho nên bài toán hiệu quả khi lời giải nằm gần gốc của cây tìm kiếm (nghĩa là đỉnh ra gần đỉnh vào) Nhưng do sử dụng cấu trúc hàng đợi nên đã giảm đáng kể số lần tìm kiếm giải vô ích so với cách dùng tập hợp lưu các đỉnh kế tiếp

Trang 20

Trường hợp xấu nhất thì bài toán sẽ vét cạn toàn bộ Tuy nhiên thuật toán này luôn luôn tìm ra lời giải

Tài liệu tham khảo

Tài liệu Cấu trúc dữ liệu - Thầy Phan Chí Tùng - Đại Học Bách Khoa Đà Nẵng

vi.wikipedia.org

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

TỪ KHÓA LIÊN QUAN

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

TÀI LIỆU LIÊN QUAN

w