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

phương pháp quay lui trong kĩ thuật lập trình

9 382 2

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

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 9
Dung lượng 30,62 KB

Nội dung

phương pháp quay lui trong kĩ thuật lập trình nêu ra các ví dụ minh họa code từng bài mẫu các code được chạy thử trước khi được đưa vào word đồng thời cũng được sự kiểm tra của thầy trước khi làm tài kiệu

Trang 1

THUẬT TOÁN QUAY LUI (VÉT CẠN)

1 Mã đi tuần :

//Ham kiem tra kha nang di tiep

int KhaNang(int x, int y)//tra ve so quan ma co the dat,cua quan ma dang xet

{

int dem = 0;

int xGiaDinh, yGiaDinh;

for (int i = 0; i < 8; i++)//chay 8 vi tri

{

xGiaDinh = x + dx[i];

yGiaDinh = y + dy[i];

if (xGiaDinh >= 1 && xGiaDinh <= size && yGiaDinh >= 1 && yGiaDinh

<= size && matrix[xGiaDinh, yGiaDinh] == -1)//thuoc ban co,vi tri con trong

dem++;

}

return dem;

}

//b4 Ham ma di tuan

void MaDiTuan(int x, int y,int step)

{

int min = 8;//8 vi tri xung quanh con ma

int xTiepTheo = x, yTiepTheo = y;//vi tri tiep theo

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

{

int xGiaDinh = x + dx[i];//xet vi tri cua con ma tiep theo,bang cach lien doi no voi mang vi tri

int yGiaDinh = y + dy[i];

if (xGiaDinh >= 1 && xGiaDinh <= size && yGiaDinh >= 1 && yGiaDinh <= size && matrix[xGiaDinh, yGiaDinh] == -1)//vi tri con trong ban co va chua co quan ma nao dat vao

{

if (KhaNang(xGiaDinh, yGiaDinh) < min)//neu kha nang vi tri ma co the dat be hon 8

{

min = KhaNang(xGiaDinh, yGiaDinh);//de lay ra so vi tri co the dat quan ma tep theo

xTiepTheo = xGiaDinh;//luu vi tri cua quan ma dang xet

yTiepTheo = yGiaDinh;

}

}

}

if (xTiepTheo != x || yTiepTheo != y)//vi tri ko trung nhau_con co the di

{

step++;//buoc tang len

viTriX[step] = xTiepTheo;//vi tri thu "step" la vi tri cua quan ma nay

viTriY[step] = yTiepTheo;

matrix[xTiepTheo, yTiepTheo] = 1;//vi tri da dat quan ma moi thi danh dau lai

MaDiTuan(xTiepTheo, yTiepTheo,step);

}

else

Trang 2

{

//het duong di

if (step < size * size)

coduongdi = false;

}

}

//cách khác

const int MAX = 8;

const int dong[] = {-1,-2,-2,-1, 1, 2, 2, 1};

const int cot[] = { -2, -1, 1, 2, 2, 1, -1, -2 };

int n;

int x, y;

int a[MAX][MAX];

int stt; //buoc nhay

int so_loi_giai = 0;

void Try(int x,int y,FILE *fin);

void XuatKQ(FILE *fin);

FILE *fin;

int main()

{

cout << "Nhap vao n:";

cin >> n;

//cout << "Nhap vao vi tri xuat phat:"; //cin >> x >> y;

fopen_s(&fin,"OUT.TXT","wt");

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

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

a[x][y] = 1;

stt = 1;

Try(x, y,fin);

a[x][y] = 0;

}

if (so_loi_giai == 0)

cout << "Khong co loi giai"<<endl; fclose(fin);

system("pause");

return 0;

}

void Try(int x, int y,FILE *fin)

{

if (stt >= n*n)

XuatKQ(fin);

else

{

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

int dongmoi = x + dong[i];

int cotmoi = y + cot[i];

Trang 3

if (0 <= dongmoi && dongmoi < n &&

0 <= cotmoi && cotmoi < n &&

a[dongmoi][cotmoi] == 0) {

++stt;

a[dongmoi][cotmoi] = stt;

Try(dongmoi, cotmoi,fin);

a[dongmoi][cotmoi] = 0;

stt;

} }

}

}

void XuatKQ(FILE *fin)

{

++so_loi_giai;

cout << "Loi giai thu :" << so_loi_giai << endl;

fprintf(fin,"Loi giai thu :%d",so_loi_giai);

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

{

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

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

fprintf(fin,"%3d",a[i][j]);

} cout << endl;

fprintf(fin,"\n");

}

cout << endl;

fprintf(fin,"\n");

cout << endl;

fprintf(fin,"\n");

}

2 Tám quân hậu :

int dong[8], cot[8], cheosac[15], cheohuyen[15], dem=0;

FILE *fon;

void print ()

{

int i;

printf("Cach %d:\n",dem+1);

fprintf(fon,"Cach %d:\n",dem+1);

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

{

printf("Buoc %d: Tren dong %3d dat quan Hau o cot %d\n",i+1,i, dong[i]); fprintf(fon,"Buoc %d: Tren dong %3d dat quan Hau o cot %d\n",i+1,i, dong[i]);

}

printf("\n");

fprintf(fon,"\n");

}

void thu(int )

{

Trang 4

int j;

if (i<=7)

{

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

if (cot[j] == 1 && cheosac[i+j] ==1 && cheohuyen[i-j+7] == 1) {

dong[i] = j; cot[j] = 0;

cheosac[i+j] = 0;

cheohuyen[i-j+7] = 0;

thu(i+1);

cot[j] = 1;

cheosac[i+j] = 1;

cheohuyen[i-j+7] = 1;

} }

else

{

print();

dem++;

}

}

void tim()

{

int i, q;

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

{

cot[i] = 1;

dong[i] = -1;

}

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

{

cheosac[i] = 1;

cheohuyen[i] = 1;

}

thu(0);

printf("\n Tong so cach dat quan Hau: %d",dem);

}

3 Tìm đường trong mê cung :

//Các biến toàn cục

//Ma trận đầu vào

int a[MAX][MAX] = {

{1,0,1,1,0,0}, {0,1,0,1,0,0}, {0,1,0,1,1,0}, {1,0,0,0,1,1}, {0,1,1,1,0,0}, {1,0,0,0,1,1}, };

//Mảng để đánh dấu những ô đã duyệt qua rồi (tránh lặp)

int mark[MAX][MAX];

//Cấp của ma trận

int n=6;

//Ngăn xếp lưu đường đi của lời giải

STACK path;

Trang 5

//Mảng lưu đường đi

POS kq[100];

int nk = 0;

//Kiểm tra xem đã đến đích hay chưa

int check(POS cur, int dir){

switch (dir){

case 0: if (cur.col==0) return 1;break;//left

case 1: if (!cur.row) return 1;break;//top

case 2: if (cur.col==MAX-1) return 1;break;//right

case 3: if (cur.row==MAX-1) return 1;break;//bottom

}

return 0;

}

//Khởi tạo toàn bộ mảng mark bằng 0

void initmark(){

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

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

mark[i][j]=0;

}

//Giải thuật đệ quy và quay lui để tìm đường đi

int findpath(POS cur, int dir)

{

if (check(cur,dir)) //đã đi được đến đích thì dừng

return 1;

//Thử 8 ô xung quanh ô đang đứng, xem có đi được tiếp ko

for(int i=1; i>=-1; i )

for(int j=1; j>=-1; j )

if ((i||j) && cur.row+i>=0 && cur.row+i<MAX

&& cur.col+j>=0 && cur.col+j<MAX){

POS p; //lưu ô tiếp theo có thể đi

p.row = cur.row+i;

p.col = cur.col+j;

if (a[p.row][p.col]==a[cur.row][cur.col] &&

!mark[p.row][p.col]){ //chưa đi và đi được

mark[p.row][p.col]=1; //đánh dấu là đã đi qua int k=findpath(p,dir);//tiếp tục tìm đường

push(path,p); //lưu p vào đường đi return 1; //kết luận đi được

} }

}

return 0;

}

//Giải thuật đệ quy và quay lui để tìm đường đi

void findpath2(POS cur, int dir)

{

if (check(cur,dir)) //đã đi được đến đích thì in kq

{

cout <<"Tim duoc duong di:\n";

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

cout <<"(" <<kq[i].row <<"," <<kq[i].col <<") >"; cout <<"end\n";

}

//Thử 8 ô xung quanh ô đang đứng, xem có đi được tiếp ko

for(int i=1; i>=-1; i )

for(int j=1; j>=-1; j )

Trang 6

if ((i||j) && cur.row+i>=0 && cur.row+i<MAX

&& cur.col+j>=0 && cur.col+j<MAX){

POS p; //lưu ô tiếp theo có thể đi

p.row = cur.row+i;

p.col = cur.col+j;

if (a[p.row][p.col]==a[cur.row][cur.col] &&

!mark[p.row][p.col]){ //chưa đi và đi được

mark[p.row][p.col]=1; //đánh dấu là đã đi qua

kq[nk++] = p;

findpath2(p,dir);//tiếp tục tìm đường

nk ; //quay lui, hủy đường đi thử

mark[p.row][p.col]=0; //hủy đánh dấu

} }

}

4 Tìm đường trong đồ thị :

4.1 Giải thuật BFS:

void BFS(int a[][MAX], int n, int free[], int u){

int next[MAX], nn=0;

for(int v=0; v<n; v++) //tìm đỉnh kề chưa duyệt ttheo

if (a[u][v]==1 && free[v]==1){

cout <<v <<" "; free[v] = 0; //đánh dấu đã duyệt qua rồi

next[nn++] = v;

}

for(int v=0; v<nn; v++)

BFS(a,n,free,next[v]); //duyệt tiếp

}

4.2 Giải thuật DFS:

void DFS(int a[][MAX], int n, int free[], int u){

cout <<u <<" "; //in kết quả

free[u] = 0; //đánh dấu đã duyệt qua rồi

for(int v=0; v<n; v++) //tìm đỉnh kề chưa duyệt ttheo

if (a[u][v]==1 && free[v]==1)

DFS(a,n,free,v); //duyệt tiếp từ đỉnh v

}

4.3 Đường đi ngắn nhất :

void timduong(int a[][MAX], int n, int u, int v)

{

if (u==v) { //tìm được đường đi đến đích

for(int i=0; i<np; i++) //in đường đi

cout <<path[i] <<" >"; cout <<tongcp <<endl;

if (mincp > tongcp) { //lưu đường đi ngắn nhất

mincp = tongcp;

nminp = np;

memcpy(minpath,path,np*sizeof(int));

} }

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

if (fr[i]==1 && a[u][i]!=0) {

Trang 7

fr[i] = 0;

path[np++] = i;

tongcp += a[u][i];

timduong(a,n,i,v);

fr[i] = 1;

np ;

tongcp -= a[u][i];

} }

5 Bài toán tam giác số :

6 Bài toán hái táo :

//Hàm đệ quy quay lui để tìm đường

void tryit(int a[][MAX], int n, int row, int col){

if (col>n-1) { //đã đến đích

if (t > m) {

m = t;

memcpy(maxpath,path,n*sizeof(int)); //lưu đường đi

}

}

else {

for(int k=-1; k<=1; k++) //xét 3 vị trí

if (row+k>=0 && row+k<n){

t += a[row+k][col];

path[col] = row+k;

tryit(a,n,row+k,col+1); //đệ quy để đi tiếp

t -= a[row+k][col]; //trả lại để đi đường khác

} }

}

//Hàm vét cạn để xét tất cả các khả năng

int vetcan(int a[][MAX], int n, int p[])

{

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

tryit(a,n,i,0);

memcpy(p,maxpath,n*sizeof(int));

return m;

}

7 Sudoku:

#include "stdafx.h"

#include <stdio.h>

#define SIZE 9 //kích thước ô sudoku

#define DELTA 2

int a[SIZE+DELTA][SIZE+DELTA];

int n = SIZE;

int lastK;

void NhapData(); //nhập đề bài

void XuatKQ(); //xuất ma trận kết quả

void Try(int k);

int isOK(int i, int j, int x); //kiểm tra hợp lệ

int findLastK(); //tìm stt cuối cùng cấn điền

Trang 8

int _tmain(int argc, _TCHAR* argv[])

{

printf("TIM LOI GIAI BAI TOAN SUDOKU !!!\n");

NhapData();

lastK = findLastK();

printf("De bai:\n");

XuatKQ();

printf("Ket Qua:\n");

Try(0);

return 0;

}

//nhập dữ liệu

void NhapData()

{

int i, j, tmp;

FILE *fin = NULL;

fopen_s(&fin,"INPUT.TXT", "rt");

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

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

{

fscanf_s(fin, "%d", &tmp);

a[i][j] = tmp;

}

fclose(fin);

}

//xuất kết quả

void XuatKQ()

{

int i, j;

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

{

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

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

printf("\n");

}

}

//hàm quay lui

void Try(int )// số k là stt trong ma trận 0->80

{

int i, j, x;

while (a[k/n][k%n]!=0) //bỏ qua các ô đã điền

k++;

i = k/n; j = k%n;

for (x=1; x<=n; x++)

if (isOK(i, j, x)) //nếu trong phạm vi hàng ngang,hàng dọc và vùng 3X3

{

a[i][j] = x;//thử đặt ô đó = x

if (k==lastK)// nếu đây là ô cuối cùng cấn điền thì kết thúc

XuatKQ();

else //nếu chưa là ô cuối cùng

Try(k+1);//thử tìm lới giải ô tiếp theo

a[i][j] = 0; //trả lại để thử cách khác

}

}

Trang 9

//hàm kiểm tra xem trong phạm vi hàng ngang,hàng dọc và vùng 3X3 có chứa x ko // có trả về 0 ngược lại trả về 1

int isOK(int , int , int )

{

int k, t;

int tmpX, tmpY;

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

if (a[i][k] == x

return 0;

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

if (a[k][j] == x

return 0;

tmpX = i%3; tmpY = j%3;

for (k=i-tmpX; k<=i-tmpX+2; k++)

for (t=j-tmpY; t<=j-tmpY+2; t++)

if (a[k][t] == x

return 0;

return 1;

}

//tìm vị trí chưa điền cuối cùng từ 0->80

int findLastK()

{

int i, j;

for (i=n-1; i>=0;i )

for (j=n-1; j>=0; j )

if (a[i][j]==0)

{

return (i*n + j);

}

}

Ngày đăng: 09/09/2015, 17:01

TỪ KHÓA LIÊN QUAN

w