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

Đồ án thuật toán quay lui

18 1,3K 11

Đ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 18
Dung lượng 57,67 KB

Nội dung

Trong cuộc sống có nhiều vấn đề buộc ta phải lựa chọn hoặc tìm ra những phương án để giải quyết được vấn đề. Trong toán học cũng thế, để giải một bài toán đòi hỏi ta phải chọn được phương án giải quyết bài toán một cách tối ưu để thu được kết quả mong muốn. Vấn đề đặt ra ở đây là, trong Tin học với mỗi bài toán thường có rất nhiều phương pháp giải. Nhưng để tìm được phương pháp giải tối ưu không phải là vấn đề đơn giản. Giả sử đặt vào bài toán tìm trường hợp tối ưu trong các liệt kê tổ hợp luôn là một trong những bài toán được quan tâm hàng đầu hiện nay. Một bài toán liệt kê tổ hợp cần được đảm bảo không được bỏ sót cũng như trùng lặp bất kỳ một trường hợp nào. Phương pháp quay lui (backtracking) là một trong những phương pháp liệt kê tổ hợp hữu hiệu và mang tính phổ dụng cao. Tuy là thuật toán quay lui là không mới, không tối ưu trong việc giải quyết một số bài toán, nhưng cũng có nhiều bài toán ứng dụng như hoán vị, tập con, tìm đường đi hay mê cung thì cũng chỉ có thuật toán quay lui là lựa chọn phù hợp, nó giúp giải quyết vấn đề một cách đơn giản và dễ dàng hơn. Vì vậy mà “thuật toán quay lui và ứng dụng” được lựa chọn làm đề tài. Ý tưởng cơ bản của “thuật toán quay lui” là liệt kê hết tất cả các khả năng có thể, hay còn gọi là phương pháp vét cạn, duyệt hết cấu hình

Trang 1

ĐẠI HỌC ĐÀ NẴNG TRƯỜNG ĐẠI HỌC SƯ PHẠM

KHOA TIN HỌC

ĐỒ ÁN THUẬT TOÁN

ĐỀ TÀI

THUẬT TOÁN QUAY LUI

VÀ ỨNG DỤNG

ĐỂ TÌM ĐƯỜNG ĐI TRONG MÊ CUNG

Đà Nẵng – 2018

Trang 2

Mục lục

Trang 3

MỞ ĐẦU

1 Lí do chọn đề tài

Trong cuộc sống có nhiều vấn đề buộc ta phải lựa chọn hoặc tìm ra những phương án để giải quyết được vấn đề Trong toán học cũng thế, để giải một bài toán đòi hỏi ta phải chọn được phương án giải quyết bài toán một cách tối ưu để thu được kết quả mong muốn Vấn đề đặt ra ở đây là, trong Tin học với mỗi bài toán thường có rất nhiều phương pháp giải Nhưng để tìm được phương pháp giải tối ưu không phải là vấn đề đơn giản Giả sử đặt vào bài toán tìm trường hợp tối ưu trong các liệt kê tổ hợp luôn là một trong những bài toán được quan tâm hàng đầu hiện nay Một bài toán liệt kê tổ hợp cần được đảm bảo không được bỏ sót cũng như trùng lặp bất kỳ một trường hợp nào Phương pháp quay lui (backtracking) là một trong những phương pháp liệt kê tổ hợp hữu hiệu và mang tính phổ dụng cao Tuy là thuật toán quay lui là không mới, không tối ưu trong việc giải quyết một số

bài toán, nhưng cũng có nhiều bài toán ứng dụng như hoán vị, tập con, tìm đường

đi hay mê cung thì cũng chỉ có thuật toán quay lui là lựa chọn phù hợp, nó giúp

giải quyết vấn đề một cách đơn giản và dễ dàng hơn Vì vậy mà “thuật toán quay lui và ứng dụng” được lựa chọn làm đề tài

Ý tưởng cơ bản của “thuật toán quay lui” là liệt kê hết tất cả các khả năng có thể, hay còn gọi là phương pháp vét cạn, duyệt hết cấu hình

2 Mục tiêu và nhiệm vụ

- Nghiên cứu tổng quan về thuật toán quay lui (lịch sử ra đời, cơ sở lý thuyết, khái

niệm, những ưu điểm, hạn chế của thuật toán)

- Ứng dụng của thuật toán quay lui vào các bài toán điển hình

3 Cấu trúc báo cáo

Chương 1: Cơ sở lý thuyết về thuật toán quay lui

Chương 2: Phát biểu vấn đề

Trang 4

Chương 3: Kết quả và ứng dụng

CHƯƠNG 1: CƠ SỞ LÝ THUYẾT 1.1 Lịch sử ra đời

- “Backtrack” (quay lui) được giới thiệu lần đầu tiên bởi nhà toán học người Mỹ Dr.D.H Lehmer vào năm 1950

- R.J Walker là người đầu tiên mô phỏng thuật toán này vào năm 1960

- Sau đó, thuật toán quay lui được S Golamb và L Baumert phát triển

1.2 Tổng quan về thuật toán quay lui

1.2.1 Khái niệm

- Quay lui (backtracking) là phương pháp thử các khả năng của bài toán cho đến

khi tìm thấy lời giải đúng Phương pháp quay lui về bản chất là quá trình tìm kiếm

theo chiều sâu (Depth first search – DFS) trên đồ thị không gian trạng thái của bài

toán

1.2.2 Dấu hiệu nhận biết bài toán có thể sử dụng thuật toán quay lui

- Một bài toán liệt kê tổ hợp luôn cần phải đảm bảo hai nguyên tắc, đó là: không

được bỏ sót một cấu hình và không được trùng lặp một cấu hình Có thể nói rằng phương pháp liệt kê là cách cuối cùng để có thể giải được một số bài toán tổ hợp hiện nay Một trong những phương pháp liệt kê có tính phổ dụng cap đó là thuật toán quay lui

- Một số bài toán liệt kê đơn giản:

 Liệt kê các tổ hợp của hoán vị

 Liệt kê các số tự nhiên chia hết cho 5

 Liệt kê các đường đi để thoát khỏi mê cung

Trang 5

1.2.3 Ý tưởng của thuật toán

Tại mỗi bước, nếu có lựa chọn được chấp nhận thì ghi nhận lại lựa chọn này

và tiến hành thử các bước thử tiếp theo Còn ngược lại không có lữa chọn nào thích hợp thì làm lại bước trước, xóa bỏ ghi nhận và quay về chu trình thử các lựa chọn còn lại

Hành động này được gọi là quay lui, thuật toán thể hiện phương pháp này gọi

là quay lui

Điểm quan trọng của thuật toán là phải ghi nhỡ mỗi bước đi qua để tránh trùng lặp khi quay lui Dễ thấy là các thông tin này được lưu trữ vào một ngăn xếp, nên thuật toán thể hiện ý thiết kế một cách đệ quy

1.2.4 Các bước thiết kế thuật toán quay lui

Để xây dựng thuật toán quay lui, chúng ta cần phải phân tích bài toán để thiết kế bốn bước cơ bản dưới đây:

1/ Chọn cách biểu diễn giải pháp

2/ Xây dựng các tập rẽ nhánh A1, A2…An vàxếp thứ tự các phần tử của chúng sao cho dễ xử lý

3/ Xây dựng các điều kiện từ ràng buộc của bài toán để xác định một giải pháp từng phần có là triển vọng không, được gọi là điều kiện tiếp tục

4/ Chọn tiêu chí để xác định một giải pháp từng phần có là giải pháp cuối cùng không

1.2.5 Mô tả

Lời giải của bài toán thường biểu diễn một vec tơ gồm n phần tử A= (A1…An) Phải thỏa mãn các điều kiện nào đó Để chỉ ra lời giải A, ta phải xây dựng dần các thành phần lời giải Ai

Tại bước i:

- Đã xây dựng xong các thành phần A1,….Ai-1

Trang 6

- Xây dựng thành phần Ai bằng cách lần lượt thử các khả năng mà Ai có thể chọn

 Nếu một khả năng j nào đó phù hợp cho Ai thì ta xác định Ai theo khả năng j Thường phải thêm các thao tác ghi nhận trạng thái của bài toán để hỗ trợ cho bước quay lui Nếu i=n thì ta có được một lời giải, ngược lại thì tiến hành bước i+1 để xác định xi+1

 Nếu không có một khả năng nào chấp nhận được cho xi thì ta lùi lại bước trước (bước i-1) để xác định lại thành phần Ai-1

Để đơn giản, ta giả định các khả năng lựa chọn cho các Ai tại mỗi bước như nhau, dó đó ta phải có thêm một thao tác kiểm tra khả năng j nào là chấp nhận cho

Ai

Ta có thể trình bày quá trình tìm kiếm lời giải qua thuật toán quay lui bằng cây sau:

Giải thuật tổng quát

Tìm nghiệm bằng thuật toán quay lui có thể chuyển về tìm kiếm trên cây khôn gian trạng thái, với cây được xây dựng từng mức như sau:

- Các nút con của gốc (thuộc mức 1) là các khả năng có thể chọn cho x1

Trang 7

- Giả sử Ai-1 là một nút ở mức thứ i-1, khi đó các nút con của Ai-1 là các khả năng

mà Ai có thể chọn, một khi đã tìm được các thành phần A1…Ai-1

Như vậy, mỗi nút Ai của cây biểu diễn một lời giải bộ phận, đó là các nút nằm trên đường đi từ gốc đến nút

Ta có thể nói việc tìm kiếm nghiệm bằng thuật toán quay lui chính là tìm kiếm theo chiều sâu trên cây không gian các trạng thái

1.2.6 Cấu trúc chung của thuật toán quay lui

Input: Các tập hợp A 1 , A 2 , …., A n

Output: Các tập con S của A 1 x A 2 x … x A n thỏa mãn ràng buộc của bài toán

Sử dụng đệ quy

algorithm Quaylui_Dequy (k)

begin

if ( S= ( s1, s2, …, sk-1 ) là giải pháp ) then xuly (s)

else

// Thử tất cả các giá trị có thể

for j  1 to |Ak| do

Sk  akj

// A k = { a k1 , a k2 , }

if ( ( s1, s2, …, sk là có triển vọng ) then

Quaylui_Dequy (k+1) // Lựa chọn tiếp theo

endif

endof

endif

end

Sử dụng vòng lặp

algorithm Quaylui_Vonglap (k)

Trang 8

k  1, ik  0

while ( k > 0 ) do

ik  ik + 1

v  false

while ( v = false and ik ≤ |Ak| ) do

sk = ak

ik

if ( ( s1, …, sk ) là có triển vọng ) then

v  true

else ik  ik+1

endif

endwhile //Thử giá trị tiếp theo

if ( v = true ) then

if ( S = ( s1, …., sk ) là giải pháp cuối cùng ) then xuly(s)

else

k  k+1

//Xây dựng thành phần tiếp theo

ik  0

endif

else k  K-1

endif

//Quay lui lại thành phần trước đó

endwhile

end

Trang 10

CHƯƠNG 2 : PHÁT BIỂU VẤN ĐỀ 2.1 Đề bài

- Giả sử một mê cung được định nghĩa là một lưới có n x n ô Tìm đường đi trong

mê cung xuất phát từ ô (1,1) đến ô (n,n) sao cho mỗi ô chỉ qua đúng một lần Biết rằng, chỉ cho phép di chuyển lên, xuống, trái và phải nếu như vị trí tiếp theo là trống và nằm trong mê cung

2.2 Phân tích

Chúng ta có thể phân tích bài toán mê cung như sau:

- Dùng ma trận M [ 1 n, 1 n ] để lưu trữ mê cung sao cho: M [ i,j ] = 0 nếu ô (i,j)

là rỗng, và ngược lại M [ i,j ] = 1 nếu ô (i,j) có chướng ngại vật

- Tìm tất cả các đường đi S = ( s1, s2, …., sn ), sk trong {1,…., n} x {1,…., n} chỉ ra chỉ số tương ứng ô đi đến các bước k sao cho:

 s1 là ô xuất phát ( 1, 1 )

 sm là ô đích ( n,n )

 M[sk] = 0 ( ô được đi đến phải rỗng )

 si ≠ sj với mọi i ≠ j ( mỗi ô chỉ đi qua nhiều nhất một lần )

 sk-1 và sk là các ô kề nhau

2.3 Thiết kế thuật toán

Từ những phân tích trên, chúng ta có các bước thiết kế cho thuật toán quay lui như sau:

1/ Biểu diễn giải pháp: Giải pháp được biểu diễn bởi véc – tơ S = (s1, s2, …., sn) với

sk là ô đi đến ở bước k

2/ Xây dựng tập đầu vào A1, A2, …., An và thứ tự các phần tử: Ak = {1, …, n} x {1,

…, n}, với mọi k, các phần tử sẽ được xử lý tăng dần

3/ Điều kiện tiếp tục: Giải pháp từng phần S = (s1, s2, …, sn) phải thoản mãn ràng buộc bài toán là:

Trang 11

 M[sk] = 0

 si ≠ sj với mọi i ≠ j

 sk-1 và sk là các ô kề nhau

4/ Tiêu chí để xác định một giải pháp từng phần có là giải pháp cuối cùng: sk là ô đích ( n,n )

Thuật toán quay lui tìm đường đi trong mê cung

Input: số ô n, ma trận mê cung M [ 1 n, 1 n ]

Output: in tất cả các cách đi

alogrithm MeCung (k)

begin

if ( s [k-1] = ( n,n ) ) then print ( s [1 k-1] )

else

//Đi lên

s [k] i  s [k-1] i-1, s [k] j  s [k-1] j

if (TrienVong ( s [1…k] ) ) then MeCung ( k+1 ) endif

// Đi xuống

s [k] i  s [k-1] i+1, s [k] j  s [k-1] j

if (TrienVong ( s [1…k] ) ) then MeCung ( k+1 ) endif

//Qua trái

s [k] i  s [k-1] i, s [k] j  s [k-1] j - 1

if (TrienVong ( s [1…k] ) ) then MeCung ( k+1 ) endif

// Qua phải

s [k] i  s [k-1] i-1, s [k] j  s [k-1] j + 1

if (TrienVong ( s [1…k] ) ) then MeCung ( k+1 ) endif

endif

end

Hàm TrienVong

Trang 12

TrienVong ( s[1…k] )

begin

if ( s[k] i < 1 or s[k] I > n or s[k] j < 1 or s[k] j > n ) then

return false // Ô ngoài mê cung

endif

if ( M[ s [k] i, s [k] j ] = 1) then return false endif

for q from 1 to k-1 do

if ( s[k] i = s [q] i and s [k] j = s [q] j ) then

return false

endif

endof

return true

end

Trang 13

CHƯƠNG 3: KẾT QUẢ VÀ ỨNG DỤNG

[Nêu các ứng dụng, kết quả của thuật toán, chương trình ]

3.1

3.2

KẾT LUẬN

1 Kết luận

- Với vấn đề đặt ra “thuật toán quay lui và ứng dụng để tìm đường đi trong mê

cung”, đồ án đã đạt được một số kết quả:

 Tìm hiểu cơ sở lý thuyết của thuật toán quay lui

 Ứng dụng để tìm đường đi trong mê cung

 Cài đặt chương trình và chjay thử

nghiệm-Đồ án có thể được ứng dụng trong quá trình học tập của sinh viên

2 Hướng nghiên cứu tiếp theo

- Tiếp tục tìm hiểu các bài toán có thể giải quyết được bằng thuật toán quay lui

- Kết hợp thuật toán quay lui với một số kĩ thuật như nhánh cận nhằm đạt hiệu quả tốt nhất

- Xây dựng chương trình ứng dụng có giao diện trực quan, dễ sử dụng hơn

Trang 14

TÀI LIỆU THAM KHẢO

1 https://ndtls.com/de-tai-ung-dung-thuat-toan-quay-lui-vao-giai-bai-toan-liet-ke/

2.https://vi.wikipedia.org/wiki/Quay_lui_(khoa_h%E1%BB%8Dc_m

%C3%A1y_t%C3%ADnh)

3 http://www.giaithuatlaptrinh.com/?p=58

4 https://viblo.asia/p/thuat-toan-quay-lui-backtracking-bJzKmLbD59N

5 http://vietjack.com/cau-truc-du-lieu-va-giai-thuat/thuat-toan-quay-lui.jsp

6 http://simplecodecjava.blogspot.com/2015/10/thuat-toan-thuat-toan-quay-lui-back.html

7 http://v1study.com/giai-thuat-va-lap-trinh-thuat-toan-quay-lui.html

Trang 15

PHỤ LỤC

Chương trình minh họa 1.

#include <stdio.h>

#include <stdlib.h>

#include <conio.h>

#define nmax 1000

FILE *fpin, *fpout;

int s_i[nmax], s_j[nmax];

int di[4]={-1, 0, 0, 1};

int dj[4]={0, -1, 1, 0};

int M[nmax][nmax];

int n;

void doc_du_lieu() {

int i,j,l;

/* doc du lieu vao tu tep tin input.txt */

if ((fpin = fopen("input.txt", "r")) == NULL) { printf ("khong the mo tep du lieu vao! \n"); exit(1);

}

fscanf (fpin, "%d", &n);

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

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

fscanf (fpin, "%d", &M[i][j]);

fclose (fpin);

Trang 16

int trienvong (int k) {

int q;

if (s_i[k]<1 || s_i[k]>n || s_j[k]<1 || s_j[k]>n) return 0;

if (M[s_i[k]][s_j[k]] == 1) return 0;

for (q=1; q<k; q++)

if (s_i[k] == s_i[q] && s_j[k] == s_j[q]) return 0;

return 1;

}

void mecung(int k) {

int q;

if (s_i[k-1] == n && s_j[k-1] == n) {

for (q=1; q<k; q++)

fprintf (fpout, "(%d %d)", s_i[q], s_j[q]); fprintf (fpout, ".\n");

}

else

for (q=0; q<4; q++) {

s_i[k] = s_i[k-1] + di[q];

s_j[k] = s_j[k-1] + dj[q];

if (trienvong (k)) mecung(k+1);

}

}

Trang 17

int main() {

doc_du_lieu();

//mo file ghi ket qua output.txt

if ((fpout = fopen("output.txt", "w")) == NULL){

printf ("khOng the mo tep tin ghi ket qua \n");

exit (1);

}

s_i[1] = s_j[1] =1;

mecung(2);

fclose (fpout);

return 0;

}

Giải thích chương trình

- Dữ liệu đầu vào được lưu trong tệp tin input.txt Có cấu trúc như sau: dòng đầu tiên chứa một số nguyên dương n; các dòng tiếp theo là ma trận n x n biểu diễn mê cung (0 là rỗng, 1 là chướng ngại vật)

- Các cách đi được ghi trong tệp tin output.txt, mỗi cách đi thể hiện bằng một

véc-tơ S = ( s1, s2, …., sn) được ghi trên một dòng

- Lệnh FILE *fpin, *fpout dùng để gọi tập tin văn bản vào chương trình

- Lệnh fscanf (fpin, "%d", &n) đọc dữ liệu từ file input.txt

- Lệnh fprintf(fpout, "(%d %d)", s_i[q], s_j[q]) dùng để in vào file output.txt

Ngày đăng: 27/09/2018, 22:43

TỪ KHÓA LIÊN QUAN

w