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

Đồ Án Trên bàn cờ n x n hãy xếp 2n con hậu sao cho mỗi hàng và mỗi cột có đúng 2 con hậu.

15 637 1

Đ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 15
Dung lượng 194 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Tuy nhiên có những trường hợp việc tìm ra một thuật toán với những tính chất đòi hỏi như trên rất khó khăn nhưng có cách giải có thể vi phạm các tính chất của thuật toán nhưng lại khá đơ

Trang 1

TRƯỜNG ĐẠI HỌC BÁCH KHOA

KHOA CÔNG NGHỆ THÔNG TIN

- -BÁO CÁO

ĐỒ ÁN MÔN HỌC

CẤU TRÚC DỮ LIỆU VÀ

THUẬT TOÁN

ĐỀ 38 : Trên bàn cờ n x n hãy xếp 2n con hậu sao cho mỗi hàng và mỗi

cột có đúng 2 con hậu

Giáo viên hướng dẫn : Phan Thanh Tao

Sinh viên thực hiện : Phan Văn Tuấn

Nguyễn Trung Dũng

Phùng Duy Thiện Trương Công Hưng

Lớp : 07T1

Nhóm : 12A

Đà Nẵng, 12/2009

Trang 2

MỤC LỤC

MỤC LỤC 2

BÁO CÁO ĐỒ ÁN 3

Phần I Cơ sở lý thuyết 3

I.1 Khái niệm về đệ quy 3

I.2 Định nghĩa theo đệ quy 4

I.3 Phân loại kĩ thuật đệ quy: 4

I.4 Cấu trúc của thuật toán đệ quy 4

I.5 Kết luận: 5

Phần II Phân tích thuật toán và chương trình: 5

II.1 Cấu trúc dữ liệu: 5

II.2 Thuật toán giải quyết: 6

II.3 Chương trình: 6

II.4 Giải thích chương trình: 10

II.5 Kết quả chương trình: 12

Phần III Kết luận: 15

Trang 3

BÁO CÁO ĐỒ ÁN

CẤU TRÚC DỮ LIỆU VÀ THUẬT TOÁN

Nội dung đề tài:

Trên bàn cờ vua kích thước n x n, hãy xếp 2n con hậu sao trên mỗi hàng và mỗi cột có đúng 2 con hậu

Phần I Cơ sở lý thuyết

I.1 Khái niệm về đệ quy:

Thuật toán đệ qui là một trong những sự mở rộng của khái niệm thuật toán Như đã biết, một thuật toán được đòi hỏi phải thỏa mãn các tính chất:

- Tính xác định

- Tính hữu hạn hay tính dừng

- Tính đúng

Tuy nhiên có những trường hợp việc tìm ra một thuật toán với những tính chất đòi hỏi như trên rất khó khăn nhưng có cách giải có thể vi phạm các tính chất của thuật toán nhưng lại khá đơn giản và được chấp nhận Ví dụ những trường hợp bài toán có thể được phân tích và đưa tới việc giải một bài toán cùng loại nhưng cấp độ thấp hơn, chẳng hạn có dữ liệu nhập nhỏ hơn, giá trị cần tính toán nhỏ hơn, v.v Ta cũng thường thấy những định nghĩa về những đối tượng, những khái niệm dựa trên chính những đối tượng, những khái niệm đó như những ví dụ dưới đây

Ví dụ 1: Ðịnh nghĩa giai thừa

Giai thừa của một số tự nhiên n, ký hiệu là n!, được định nghĩa bằng cách qui nạp như sau:

0! = 1,

n! = (n-1)!*n, với mọi n > 0

Ví dụ 2: Ðịnh nghĩa dãy số Fibonacci  f1, f2, , fn,  :

f0 = 1,

Trang 4

f1 = 1,

fn = fn-1 + fn-2 , vớ mọi n > 1

Thuật toán để giải các bài toán trong những trường hợp như trên thường được viết dựa trên chính nó, tức là trong các bước của thuật toán có thể có trường hợp thực hiện lại chính thuật toán đó (nhưng thường là với dữ liệu nhập có cở thấp hơn, hay có cấp độ thấp hơn) Những thuật toán loại này được gọi là những thuật toán đệ quy

I.2 Định nghĩa theo đệ quy

Một khái niệm X được định nghĩa theo đệ quy nếu trong định nghĩa X có sử dụng ngay chính khái niệm X

 Ví dụ 1: Định nghĩa số tự nhiên

- 0 là một số tự nhiên

- n là số tự nhiên nếu n - 1 là số tự nhiên

 Ví dụ 2: Định nghĩa hàm giai thừa n!

- 0! = 1

- Nếu n > 0 thì n! = n(n - 1)!

I.3 Phân loại kĩ thuật đệ quy: có 3 loại

- Vét cạn: đi tới tất cả điểm dừng rồi mới quay lại

- Cắt tia Alpha – Beta và nhánh cận: là 2 kĩ thuật cho phép không cần thiết phải đi tới tất cả các điểm dừng mà chỉ cần đi đến 1 số điểm nào đó và dựa vào 1 số suy luận để có thể quay lui sớm

I.4 Cấu trúc của thuật toán đệ quy

Trong thuật giải đệ qui thường gồm 2 phần: phần cơ sở và phần đệ quy

Phần cơ sở gồm các trường hợp không cần thực hiện lại thuật toán, tức là các trường

hợp dừng mà ta có thể trực tiếp giải quyết được bài toán (hay không có yêu cầu gọi đệ qui) Trong thuật toán tìm số hạng thứ n của dãy Fibonacci ở trên, bước 1 trong thuật toán là phần cơ sở của thuật giải đệ qui

Trang 5

Phần đệ quy là phần trong thuật toán có yêu cầu gọi đệ quy, tức là yêu cầu thực hiện

lại thuật toán ở cấp độ thấp hơn Trong thuật toán tìm số hạng thứ n của dãy Fibonacci

ở trên, bước 2 trong thuật toán là phần đệ quy Trong phần đệ quy, yêu cầu gọi đệ qui thường được đặt trong một điều kiện kiểm tra việc gọi đệ quy

Cần lưu ý rằng phần cơ sở luôn luôn phải có hay nói cách khác là phần đệ quy luôn luôn phải nằm trong điều kiện kiểm soát dừng đệ quy, vì nếu không thì thuật toán

sẽ bị lặp vô hạn do việc gọi đệ quy luôn được thực hiện

Về mặt cài đặt, nếu như có sử dụng biến cục bộ trong thủ tục hay hàm đệ quy thì các biến này được tạo ra và được đặt trong vùng nhớ "STACK" Do đó quá trình gọi đệ quy dễ gây ra tình trạng tràn stack (stack overflow) Trong nhiều trường hợp có thể được người ta tìm cách viết lại thuật toán đệ quy dưới dạng lặp

I.5 Kết luận :

Đệ quy là 1 công cụ có vai trò rất quan trọng đối với những người lập trình hiện nay Đệ quy tỏ ra rất mạnh mẽ trong các bài toán vét cạn, tìm kiếm, đồ thị… Hiện nay

có rất nhiều bài toán chưa có lời giải không đệ quy ( Ví dụ bài toán Tháp hà Nội) Vì vậy ta cần phải nghiên cứu và phát huy, áp dụng thuật toán này nhiều hơn nữa

Tuy vậy thuật toán đệ quy lại có độ phức tạp tương đối lớn, ta chỉ nên sử dụng chúng khi thực sự cần thiết

Phần II Phân tích thuật toán và chương trình :

II.1 Cấu trúc dữ liệu :

Để giải quyết bài toán đặt hậu trên đầu tiên ta phải tìm ra cách lưu cấu trúc dữ liệu cho

vị trí mỗi con hậu đặt vào trong bàn cờ kích thước n x n

Ta sẽ dùng 2 mảng ( 1 mảng 1 chiều, 1 mảng 2 chiều có 2 cột) để lưu trữ vị trí các quân

cờ và cũng phục vụ cho thuật toán đặt hậu thõa yêu cầu, đồng thời tiết kiệm không gian

bộ nhớ thay vì việc khai báo 1 ma trận 2 chiều kích thước n x n

Mảng thứ nhất là doc[n] [2] có n hàng và 2 cột mục đích của việc chọn mảng

này có 2 cột cũng là do mỗi hàng ta sẽ đặt 2 quân hậu, vì vậy mỗi phần tử của mỗi hàng

sẽ lưu lại vị trí của mỗi quân cờ trong 2 quân cờ được đặt vào hàng đó

Mảng thứ hai là mảng ngang[n] có n phần tử trong mảng này ta cho chúng chỉ nhận các phần tử 0, 1 hoặc 2 mảng này dùng để chứa số lượng hậu còn có thể đặt trên

cột này ( ngang[i]=2 nghĩa là cột i còn có thể đặt 2 quân hậu nữa) Khi ta tiến hành đặt

1 quân hậu vào cột i đồng thời ta phải cho ngang[i] – 1, giảm số lượng quân hậu có thể

đặt nữa ở cột i ngang[i] = 0 nghĩa là ở cột i không thể đặt thêm hậu nữa

Trang 6

II.2 Thuật toán giải quyết:

- Ta tiến hành dùng thuật toán đệ quy để đặt các quân hậu thõa mãn yêu cầu

- Đầu tiên là khởi tạo dữ liệu ban đầu cho 2 mảng lưu dữ liệu Đối với mảng ngang[] khởi tạo giá trị ta cho các phần tử nhận giá trị 2, nghĩa là chưa có quân hậu nào được đặt trong mỗi cột Đối với mảng cot[] ta cho chúng nhận các giá trị -1 để phân biệt với các giá trị số nguyên dương mà chúng nhận được khi đã đặt hậu

- Kiểm tra điều kiện “doc[i][j]==-1&&ngang[k]>0&& doc[i][0]<k” xem tại vị trí (i,j) có thể đặt hậu hay không Điều kiện doc[i][0]<k làm cho quân thứ 2 đặt trong hàng

này luôn đặt sau quân đầu tiên ví dụ như ta đã đặt hậu (2,3) thì không thể lại đặt (3,2) được vì chúng giống như nhau, ràng buộc điều kiện quân thứ 2 phải luôn đặt sau quân đầu tiên

- Quân hậu được đặt tại ô (i,k) tương đương với việc cho doc[i][j] = k với j = 0 hoặc 1.

- Tiếp theo là gọi đệ quy đặt quân hậu tiếp theo:

if(j==0) dathau(i,j+1); else dathau(i+1,0);

- Đến khi thõa điều kiện “(i==n-1&&j==1)”thì gọi hàm in kết quả ra màn hình “(i

== n-1&&j = 1)” nghĩa là đã đặt được quân hậu cuối cùng trên bàn cờ

II.3 Chương trình:

#include <stdio.h>

#include <conio.h>

#include <stdlib.h>

int doc[50][2],ngang[50],n;

unsigned long dem;

char tt,t;

void gach(int i, int j, int m)

{

int k;

for(k=1;k<=m;k++) {gotoxy(i,j); cprintf("||");j++;}

}

void gioithieu()

{

textcolor(LIGHTBLUE);// chu mau xanh duong nhat

gotoxy(35,2);

cprintf("WELCOME !");

Trang 7

cprintf("***** -*****");

gotoxy(32,4);

cprintf(" -*** -");

textcolor(YELLOW);// chu mau vang

gotoxy(24,7);

cprintf("Khoa CNTT - DH Bach Khoa DN");

gotoxy(35,13);

cprintf("DE TAI ");

gotoxy(34,14);

cprintf(" -** -");

gotoxy(16,8);

cprintf("DO AN MON HOC CAU TRUC DU LIEU & THUAT TOAN");

textcolor(MAGENTA);// chu mau tin

gotoxy(13,5);

cprintf("==================================================");

gotoxy(13,10);

cprintf("==================================================");

gach(13,5,6); gach(61,5,6);

textcolor(LIGHTGREEN); // chua mau xanh la cay nhat

gotoxy(15,12);

cprintf("===============================================");

gotoxy(15,17);

cprintf("===============================================");

gach(15,12,6);gach(60,12,6);

gotoxy(3,19);

cprintf("Giao vien huong dan:");

gotoxy(3,21);

cprintf("Sinh vien thuc hien:");

gotoxy(3,25);

cprintf("Lop Nhom - ");

textcolor(WHITE);// chu mau trang

gotoxy(29,19);

cprintf("PHAN THANH TAO");

gotoxy(29,21);

cprintf("PHAN VAN TUAN");

gotoxy(29,22);

cprintf("PHUNG DUY THIEN");

gotoxy(29,23);

cprintf("NGUYEN TRUNG DUNG");

gotoxy(29,24);

Trang 8

cprintf("TRUONG CONG HUNG");

gotoxy(7,25);

cprintf("07T1");

gotoxy(17,25);

cprintf("C4");

gotoxy(22,25);

cprintf("12A");

textcolor(RED);// chu mau do

gotoxy(17,15);

cprintf("Tren ban co nxn hay xep 2n con hau sao cho ");

gotoxy(17,16);

cprintf("tren moi hang va moi cot co dung 2 con hau");

gotoxy(24,27);

cprintf("Press any key to continue ");

getch();

clrscr;

}

void khoitao()

/* Khoi tao ban dau ngang[i]=2 nghia la cot i chua dat duoc con hau nao,

doc[i][j]=-1 nghia la dong i, cot j chua dat hau*/

{

int i,j;

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

ngang[i]=2;

for(j=0;j<2;j++) doc[i][j]=-1;

} }

void printbis()

/* in ra cac duong ke de de phan biet*/

{

int k;

printf("\n|");

for(k=0;k<n;k++) printf(" -|");

}

/* Xuat ra man hinh theo dang toan do*/

void print1()

{

int i;

dem++;

Trang 9

printf("\n%2d) ",dem);

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

printf(" [%2d,%2d]", doc[i][0]+1,doc[i][1]+1);

}

void print2()

{

int i,j;

char c;

printf("\nMuon thoat thi an phim t / T");

printf("\nMuon xem tiep bang cach bieu dien toa do thi an phim c / C");

dem++; // biến dem dùng để dem số cách đặt hậu thõa mãn

printf("\n\n%d)\n",dem);

printbis();

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

printf("\n|");

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

if(j==doc[i][0||j==doc[i][1]]) printf(" X |"); else printf(" |");

printbis();

/* Tai o co dat hau thi in ra dau X*/

} printf("\n");

c=getch();

if(c=='T'||c=='t') exit(0);

if(c=='C'||c=='c') t='2';

}

void print3()

{

dem++;

}

void dathau(int i,int j)

{

int k;

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

if(doc[i][j]==-1&&ngang[k]>0&&doc[i][0]<k)

{

doc[i][j]=k;ngang[k] ;

if(j==0) dathau(i,j+1); else dathau(i+1,0);

if(i==n-1&&j==1) { if(t=='2') print1(); else if(t=='1') print2(); else print3();}

doc[i][j]=-1; ngang[k]++;

}

}

Trang 10

void main()

{

clrscr();

gioithieu();

while(1) {

dem=0;

l1:

clrscr();

textcolor(RED);

gotoxy(14,3);cprintf("==========================================="); gotoxy(14,10);cprintf("==========================================="); gach(12,3,8);gach(55,3,8);

textcolor(WHITE);

gotoxy(15,5);cprintf("Hay chon 1 trong 2 cach trinh bay sau:");

gotoxy(15,6);cprintf("1: Trinh bay truc quan bang hinh ve");

gotoxy(15,7);cprintf("2: Trinh bay bang cach bieu dien toa do");

gotoxy(15,8);cprintf("3: Xuat ra tong so cach tim duoc");gotoxy(15,12);cprintf("Ban se chon cach trinh bay: ");

scanf("%s",&t);

if(t!='1'&&t!='2'&&t!=’3’) {gotoxy(15,14);printf("Ban da chon sai, hay chon lai"); getch(); goto l1;}

do {

clrscr();

printf("\nNhap vao so dong, cot cua ban co vua (khac 1) : ");

scanf("%d",&n);

if(n==1) {printf("\nNhap sai, hay nhap lai"); getch();}

} while(n<=1);

khoitao();

if(t=='1') printf("\nDau x la o co dat hau\n");

if(t=='3') printf("\nPlease wait ");dathau(0,0);

printf("\n\nDa in ra tat ca %d cach dat hau thoa man yeu cau de bai",dem);

printf("\nBan co muon tiep tuc khong ? (C/c)");

tt=getch();

if(tt!='c'&tt!='C') break;

}

}

II.4 Giải thích chương trình:

Như đã nói, mảng ngang[] để lưu số hậu còn có thể đặt tại mỗi cột, mảng doc[] để lưu tọa độ các quân hậu đặt trên bàn cờ Ý nghĩa của các hàm trong chương trình như sau:

Trang 11

- Hàm gioithieu() in ra màn hình phông giới thiệu của nhóm làm đồ án không có tác dụng gì đến thuật toán chương trình

- Các hàm gach(int i, int j, int m), printbis() chỉ có vai trò trang trí cho dao diện không có vai trog trong thuật toán

- Hàm print1() xuất kết quả ra màn hình theo dạng tọa độ

- Hàm print2() xuất kết quả theo dạng hình vẽ ( luu ý vị trí đặt quân hậu có dấu X

- Hàm dathau(int i, int j) có vai trò quan trọng nhất trong chương trình

void dathau(int i,int j)

{

int k;

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

if(doc[i][j]==-1&&ngang[k]>0&&doc[i][0]<k)

{

doc[i][j]=k;ngang[k] ;

if(j==0) dathau(i,j+1); else dathau(i+1,0);

if(i==n-1&&j==1) { if(t=='2') print1(); else if(t=='1') print2();}

doc[i][j]=-1; ngang[k]++;

}

}

- Biến k có vai trò duyệt qua từng cột trên bàn cờ

- Điều kiện:

if(doc[i][j]==-1&&ngang[k]>0&&doc[i][0]<k)

Để kiểm tra tại vị trí (i, k) đã được đặt hậu chưa doc[i][0]<0 như đã nói để phân biệt quân thứ 2 đặt trong hàng i với quân thứ 1 đặt trong hàng này, quân thứ 2 phải đặt sau quân đầu tiên, không đặt trùng với quân đầu tiên Như vậy quân đầu tiên trong hàng luôn đặt được do khởi tạo doc[i][0]=-1 < k Đến quân thứ 2, điều kiện

doc[i][0]<k ràng buộc cho quân thứ 2 luôn đặt sau quân thứ nhất (theo thứ tự trên

bàn cờ) k là vị trí sắp đặt quân thứ 2 sau khi thõa mãn 2 điều kiện

doc[i][j]==-1&&ngang[k]>

- Việc đặt 1 quân hậu tại ô (i, k) tương ứng với câu lệnh:

doc[i][j]=k;ngang[k] ;

- Tiếp đến là gọi đệ quy thực hiện đặt quân hậu tiếp theo

if(j==0) dathau(i,j+1); else dathau(i+1,0);

Nếu đây là quân đầu tiên trên dòng thì gọi đặt quân tiếp theo, nếu không phải thì gọi đặt hậu cho dòng tiếp theo

- Sau khi đặt xong cả bàn cờ thì xuất kết quả ra màn hình

if(i==n-1&&j==1) { if(t=='2') print1(); else if(t=='1') print2();}

Nếu trước đó đã chọn phím ‘2’ thì gọi hàm print2(), nếu đã chọn phím ‘1’ thì gọi hàm print1()

- Sau khi đã xuất kết quả thì trả lại trạng thái cũ cho ô (i,k) để tìm cách đặt hậu khác

Trang 12

doc[i][j]=-1; ngang[k]++

II.5 Kết quả chương trình:

Giao diện giới thiệu:

Giao diện lựa chọn:

Phím lựa chọn là “1“ hoặc “2“ nếu ấn nút khác sẽ báo sai và yêu càu nhập lại

Trang 13

Nếu ban đầu ta chọn “1“ chương trình sẽ liệt kê kết quả theo dạng hình vẽ bàn cờ

Vì các cách xếp quân hậu thõa mãn đối với các trường hợp từ 5 hàng trở lên rất nhiều nên có thêm phím lựa chọn:

- Ấn phím t/T thoát

- Ấn phím c/C để chuyển sang cách trình bày tọa độ

Trang 14

Nếu chọn “2“ chương trình sẽ liệt kê theo dạng tọa độ

Cách liệt kê [1, 2] [1, 3] [2, 3] nghĩa là :

Hàng thứ 1: đặt quân hậu ở cột thứ 1 và 2

Hàng thứ 2: đặt quân hậu ở cột thứ 1 và 3

Hàng thứ 3: đặt quân hậu ở cột thứ 2 và 3

Muốn quay lại thực hiện tiếp thì ấn c/C

Nếu chọn 3 thì chương trình sẽ liệt kê ra rổng số kết quả tìm được với n=8 trở lên thời gian tính toán hơi lâu nên ta phải chờ

Muốn quay lại thực hiện tiếp thì ấn c/C

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

TỪ KHÓA LIÊN QUAN

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

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w