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

Bài giảng Cấu trúc dữ liệu và giải thuật – Bài 4: Kỹ thuật quay lui (Backtracking)

29 80 0

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

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

Nội dung

Bài giảng Cấu trúc dữ liệu và giải thuật – Bài 4: Kỹ thuật quay lui (Backtracking) với những kiến thức khái niệm về kỹ thuật quay lui, bài toán 8 con hậu - eight queen problem, bài toán mã đi tuần - knight tour problem, bài toán chiếc ba lô - knapsack problem.

Trang 1

Lecturer: PhD Ngo Huu Phuc

Tel: 0438 326 077 Mob: 098 5696 580 Email: ngohuuphuc76@gmail.com

Trang 2

Bài 4 K ỹ thuật quay lui

Backtracking

4.1 Khái ni ệm về kỹ thuật quay lui (6)

4.2 Bài toán 8 con h ậu - Eight Queen Problem (7)

4.3 Bài toán mã đi tuần - Knight Tour Problem (5)

4.4 Bài toán chi ếc ba lô - Knapsack Problem (6)

1 Lecture 11 – Backtracking.htm

Trang 3

4.1 Khái ni ệm kỹ thuật quay lui (1/6)

 K ỹ thuật quay lui là quá trình phân tích từ trên xuống trong không gian tìm ki ếm

 Trong trường hợp tổng quát, giả sử lời giải là một

vector:

a = (a[1], a[2], …, a[n])

trong đó, mỗi phần tử a[i] chọn từ tập hữu hạn S[i] (các kh ả năng của a[i]).

Trang 4

4.1 Khái ni ệm kỹ thuật quay lui (2/6)

 Ta s ẽ giải quyết bài toán với kích thước k, có dạng:

a = (a[1], a[2], …, a[k])

và c ố gắng mở rộng bằng việc thêm phần tử tiếp theo vào trong vector

 Sau khi thêm ph ần tử, kiểm tra xem có thể thực hiện

ti ếp được không.

 N ếu vẫn có khả năng mở rộng, tiếp tục thực hiện;

N ếu không, xóa phần tử a[k] và làm lại bài toán từ tập S[k].

Trang 5

4.1 Khái ni ệm kỹ thuật quay lui (3/6)

G ọi S[1], tập các khả năng của a tại bước đầu tiên

k = k - 1 (*backtrack*)

Trang 6

4.1 Khái ni ệm kỹ thuật quay lui (4/6)

Sub Backtrack(a, k)

If a is a solution, get it

Else

k = k +1 compute S[k]

While S[k]<>[] do a[k] = an element in S[k]

S[k] = S[k] – a[k]

Backtrack(a, k) End Sub

Trang 7

4.1 Khái ni ệm kỹ thuật quay lui (5/6)

 K ỹ thuật đệ quy có thể được dùng trong kỹ thuật

quay lui (đơn giản trong ứng dụng).

 K ỹ thuật quay lui chắc chắn đúng khi liệt kê các khả

năng có thể.

 Để tăng hiệu quả của kỹ thuật, có thể cắt bớt

không gian tìm ki ếm.

Trang 8

4.1 Khái ni ệm kỹ thuật quay lui (6/6)

Trong ph ần này, giải quyết một số bài toán, có sử dụng

k ỹ thuật quay lui:

 Bài toán 8 h ậu - Eight Queen Problem.

 Bài toán mã đi tuần - Knight Tour Problem.

 Bài toán chi ếc ba lô - Knapsack Problem.

Trang 9

4.2 Eight Queen Problem (1/7)

Bài toán : đặt 8 con hậu trên bàn cờ sao cho không có 2 con

h ậu nằm trên cùng một hàng, cột và hàng ngang.

Một lời giải Không phải lời giải

Trang 10

4.2 Eight Queen Problem (2/7)

Th ực hiện:

• Tr ạng thái: Sắp đặt từ 0 đến 8 con h ậu lên bàn cờ.

• Tr ạng thái khởi tạo: không có con h ậu nào đặt lên bàn cờ.

• Đặt từng con hậu lên bàn cờ.

• Ki ểm tra kết quả: 8 con hậu đã đặt lên bàn cờ, không có con

h ậu nào ăn được nhau.

Trang 11

4.2 Eight Queen Problem (3/7)

M ột vài cách đặt 8 con hậu lên bàn cờ (trong số 92 lời giải)

Trang 12

4.2 Eight Queen Problem (4/7)

 N ếu tại một cột, không đặt được con hậu mới, con hậu ở

c ột (hàng) đó được bỏ ra khỏi bàn cờ và chuyển xuống

c ột (hàng) trước đó.

Trang 13

4.2 Eight Queen Problem (5/7)

 N ếu xét theo cột, tại một cột, tất cả các hàng đã xét, quay tr ở lại bước trước đó (xét cột trước).

 N ếu con hậu không đặt được lên cột i, khi đó

không th ử trên cột i+1, quay lại cột i-1, bỏ con

h ậu đã đi sai.

 V ới cách tiếp cận này, có thể giảm bớt phép thử.

Trang 14

4.2 Eight Queen Problem (6/7)

typedef enum {FALSE, TRUE} bools;

void printMatrix(inta[][N], int n);

int getMarkedCol(inta[][N], intn, int row);

bools feasible(inta[][N], int n, int row, int col);

void N_Queens(inta[][N], int n, int row);

// In ma tran chua cac con hau

void printMatrix(inta[][N], int n) {

int i, j;

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

for(j=0; j<n; j++)printf("%d ", a[i][j]);

printf("\n"); }printf("\n"); }

// Lay cac cot da danh dau trong hang row

int getMarkedCol(inta[][N], intn, int row) {

int j;

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

if(a[row][j] == TRUE) return j;

printf("Loi: Khong co cot danh dau trong hang

%d.\n", row);

return-1;

Trang 15

4.2 Eight Queen Problem (6/7)

// Kiem tra xem con hau tiep theo co the dat o hang

// row, cot col khong

bools feasible(int a[][N], int n, int row, int col)

markedCol = getMarkedCol (a,n,i);

if(markedCol == col || abs(row-i) ==

abs(col-markedCol))

returnFALSE ;}

returnTRUE;

}

// Bai toan N hau

void N_Queens(inta[][N], int n, int row) {

int j;

if(row < n) {

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

if(feasible(a, n, row, j)) {a[row][j] = TRUE;

N_Queens (a, n, row+1);a[row][j] = FALSE; }}

else {k++;

printf("Trang thai thu %d\n",k);printMatrix(a, n);

}

Trang 16

4.3 Knight Tour Problem (1/5)

Trang 17

4.3 Knight Tour Problem (2/5)

Bài toán:

 Trên bàn c ờ 8 × 8 có một con mã (cách đi được định nghĩa thông thường)

 B ắt đầu từ một góc của bàn cờ và thăm tất cả các

ô c ờ khác (63 ô cờ còn lại), sao cho mỗi ô cờ chỉ đến 1 lần.

 Bài toán này được gọi là “mã đi tuần”.

Trang 18

4.3 Knight Tour Problem (3/5)

Cách ti ếp cận bài toán:

 Có nhi ều cách tiếp cận để giải bài

toán này.

 M ột trong số đó là cách giải của J.C

Warnsdorff được đưa ra năm 1823

 Theo cách c ủa J.C Warnsdorff, con

mã đi theo theo thứ tự được mã hóa

(quy ước cách đi theo hình vẽ).

 T ừ một vị trí, con mã có thể đi tối đa

đến 8 vị trí khác Tùy theo vị trí trên

bàn c ờ, các vị trí có thể này được mã

hóa theo th ứ tự từ 1 đến 8.

Trang 19

4.3 Knight Tour Problem (4/5)

void printVariant(inta[][M], int n);

void knight(int a[][M], intn, int row, int col, int num);

//dinh nghia cach di cho con ma

knight(a, M, i, j, 2);}

printf("\n");

Trang 20

4.3 Knight Tour Problem (5/5)

void knight(int a[][M], intn, int row, int col, int num)

{

// tim vi tri ke tiep

// vi tri ke tiep co gia nho nhat

// vi tri hien tai la (row,col)

int i;

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

{

int newrow = row+rowchange[i];

int newcol = col+colchange[i];

if(newrow>=0 && newrow<n && newcol>=0

&& newcol<n && a[newrow][newcol]==0)

{

a[newrow][newcol]=num;

if(num==n*n){

printVariant(a, M);

printf("\nNhan Enter de chon ket qua khac, nhan ESC de thoat!\n");

if(charc=getch()==27) exit(1);

Trang 21

4.4 Knapsack Problem (1/9)

Bài toán:

 Cho N v ật, mỗi vật có trọng lượng w(i) và giá trị v(i).

 M ột chiếc ba lô có khả năng đựng tối đa (theo trọng

lượng) là K.

 Ch ọn các vật như thế nào để tổng giá trị của chúng là

l ớn nhất và tổng trọng lượng không vượt quá K?

Ý t ưởng:

 Ta ch ọn các vật có giá trị cao nhất vào ba lô.

 Tuy nhiên, các v ật có trọng lượng khác nhau, do đó cần

ọn một cách cẩn thận!!!

Trang 23

4.4 Knapsack Problem (3/9)

 Xem xét ví d ụ sau với K = 9.

 V ới ví dụ trên, vật 4 có tỷ lệ cao nhất.

 N ếu ta lấy vật 4 này, khi đó, chỉ có thể đưa vật 1 thêm vào

Trang 24

// K: trong luong toi da cua ba lo

// used[]: cac vat co trong ba lo,

// 0: chua lay, 1: da lay

// weight[]: trong luong cua tung vat

// value[]: gia tri cua tung vat

// current[0]: trong luong hien tai

// current[1]: gia tri hien tai

// current[2]: gia tri max

// pack[]: cac vat da lay o trang thai toi uu

int nCalls=0;

void knapSack(intK, bools used[], int item, int

weight[], int value[], bools pack[], int current[], int

n);

void main() {bools used[M];

Trang 25

void knapSack(intK, bools used[], int item, int

weight[], int value[], bools pack[], int current[], int n){ nCalls++; // So loi goi

// Kiem tra da xem xet den vat cuoi

if(item == n){

// Kiem tra lai truong hop da lay vat

if(current[1] > current[2]){

printf("Tong gia tri hien tai: %d\n",current[1]);

// Luu thong tin hien tai

Trang 26

// Khong lay duoc vat nay, tiep tuc thu vat khac.

knapSack(K, used, item+1, weight, value, pack, current, n);

}}

Trang 27

// K: trong luong toi da cua ba lo

// used[]: cac vat co trong ba lo,

// 0: chua lay, 1: da lay

// weight[]: trong luong cua tung vat

// value[]: gia tri cua tung vat

// current[0]: trong luong hien tai

// current[1]: gia tri hien tai

// current[2]: gia tri max

// pack[]: cac vat da lay o trang thai toi uu

int nCalls=0;

void knapSack(intK, intused[], int item, int weight[],

int value[], int pack[], intcurrent[], int n);

Trang 28

void knapSack(intK, intused[], int item, int weight[],

int value[], int pack[], int current[], int n){

nCalls++; // So loi goi

// Kiem tra da xem xet den vat cuoi

if(item == n){

// Kiem tra lai truong hop da lay vat

if(current[1] > current[2]){

printf("Tong gia tri hien tai: %d\n",current[1]);

// Luu thong tin hien tai

Trang 29

4.4 Knapsack Problem (9/9)

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

if(pack[i]) printf("Vat %d, so lan chon %d

// Thu xem co the lay bao nhieu vat

used[item] = (K - current[0]) / weight[item];

current[0] += used[item] * weight[item];

current[1] += used[item] * value[item];

// Neu khong lay vat do lan nao ca

knapSack(K, used, item+1, weight, value, pack, current, n);

}}

Ngày đăng: 24/09/2020, 04:26

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