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

QUAY LUI TRÊN MẢNG HAI CHIỀU

29 916 6

Đ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 399 KB

Nội dung

Trong đó với các phép lặp, ta giải bài toán bằng cách thực hiện liên tiếp một số các câu lệnh trong vòng lặp cho tới khi một điều kiện nào đó được thỏa mãn.. Đệ quy quay lui là một trong

Trang 1

PHẦN I: PHẦN MỞ ĐẦU

I Lý do chọn đề tài:

Ngôn ngữ lập trình là một trong những nội dung được đưa vào dạy chính thức

ở bộ môn Tin học ở nhà trường phổ thông Như ta đã biết, các câu lệnh để giải quyết bài toán Tin học được mô tả dưới các dạng tuần tự, rẽ nhánh và lặp Trong đó với các phép lặp, ta giải bài toán bằng cách thực hiện liên tiếp một số các câu lệnh trong vòng lặp cho tới khi một điều kiện nào đó được thỏa mãn

Một kỹ thuật lập trình được sử dụng để thay thế cho các phép lặp đó là kỹ thuật đệ quy quay lui (Back tracking) Mặt khác, trong thực tế có rất nhiều bài toán đòi hỏi sự lặp đi lặp lại một cách phức tạp Và đệ quy quay lui cung cấp cho ta cơ chế giải quyết bài toán phức tạp một cách đơn giản và dễ hiểu

Đệ quy quay lui là một trong những chiến lược để giải quyết nhiều bài toán, đặc biệt là các bài toán đòi hỏi liệt kê mọi cấu hình thoả mãn Đặc biệt trong đề thi học sinh giỏi Tỉnh các năm đệ quy quay lui luôn chiếm một phần quan trọng

Đã có nhiều bài viết đề cập đến đệ quy quay lui và các vần đề xung quanh đệ quy

quay lui nhưng trong tài liệu này, tôi muốn đề cập tới “Đệ quy quay lui trên

mảng hai chiều” để làm đề tài sáng kiến kinh nghiệm của mình

II Mục đích nghiên cứu:

Đề tài: “Đệ quy quay lui trên mảng hai chiều” nhằm đạt mục đích sau:

− Giúp cho bản thân có thể hiểu rõ hơn, sâu hơn về kỹ thuật đệ quy quay lui, ứng dụng đệ quy quay lui để giải các bài toán trong Tin học, từ đó nâng cao khả năng tự học, khả năng lập trình của bản thân

− Nâng cao chất lượng bồi dưỡng học sinh giỏi môn Tin các kỳ thi

− Góp phần làm đa dạng tài liệu nghiên cứu của tổ bộ môn

III Phương pháp nghiên cứu:

Khi nghiên cứu đề tài này tôi sử dụng các phương pháp sau:

− Phương pháp nghiên cứu lý thuyết

Trang 2

− Sử dụng phương pháp thu thập thông tin và tổng hợp, phân tích, so sánh dựa trên lý thuyết về đệ quy quay lui.

− Áp dụng giải với một số bài toán cụ thể

IV Đối tượng nghiên cứu:

Đối tượng nghiên cứu của đề tài này đó chính là đệ quy quay lui và ứng dụng của quay lui để giải các bài toán trong Tin học có liên quan tới mảng hai chiều và các tài liệu, các thông tin liên quan

Nội dung nghiên cứu được trình bày theo cấu trúc sau:

1 Nhắc lại kiến thức về đệ quy quay lui (Back tracking)

2 Bài toán kinh điển: Mã đi tuần

3 Ứng dụng quay lui để giải một số bài toán xử lý trên mảng hai chiều

Kết luận

Trang 3

PHẦN II: PHẦN NỘI DUNG

1 Nhắc lại kiến thức về đệ quy quay lui (Back tracking)

1.1 Tổng quan về đệ quy quay

lui

Về bản chất, tư tưởng của phương pháp là thử từng khả năng cho đến khi tìm thấy lời giải đúng Đó là một quá trình tìm kiếm theo độ sâu trong một tập hợp các lời giải Trong quá trình tìm kiếm, nếu ta gặp một hướng lựa chọn không thỏa mãn,

ta quay lui về điểm lựa chọn nơi có các hướng khác và thử hướng lựa chọn tiếp theo Khi đã thử hết các lựa chọn xuất phát từ điểm lựa chọn đó, ta quay lại điểm lựa chọn trước đó và thử hướng lựa chọn tiếp theo tại đó Quá trình tìm kiếm thất bại khi không còn điểm lựa chọn nào nữa

Quy trình đó thường được cài đặt bằng một hàm đệ quy mà trong đó mỗi thể hiện của hàm lấy thêm một biến và lần lượt gán tất cả các giá trị có thể cho biến đó, với mỗi lần gán trị lại gọi chuỗi đệ quy tiếp theo để thử các biến tiếp theo Chiến lược quay lui tương tự với tìm kiếm theo độ sâu nhưng sử dụng ít không gian bộ nhớ hơn, nó chỉ lưu giữ trạng thái của một lời giải hiện tại và cập nhật nó

Yếu tố mấu chốt trong một thủ tục đệ quy là điều kiện duyệt và điểm dừng Với đặc trưng của mảng hai chiều là phần tử mảng được xác định bằng hai giá trị hàng

và cột, thông thường chúng ta vẫn sử dụng cặp giá trị (i,j) (hàng, cột của 1 ô) làm bước duyệt khi gọi thủ tục đệ quy

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

Procedure Try(i); {Chọn thực hiện bước thứ i}

Begin

For CÁC PHƯƠNG ÁN CHỌN do

If CHỌN ĐƯỢC then

Begin

- THỰC HIỆN BƯỚC ĐI THỨ i;

- IF THÀNH CÔNG then THÔNG BÁO KẾT QUẢ

Else Try(i+1);

-HỦY BƯỚC ĐI THỨ i; {Quay lui}

End;

Trang 4

- Thủ tục trên sẽ được khởi động bởi lệnh: Try(1);

2 Bài toán kinh điển: Mã đi tuần

2.1 Đề bài:

Mã đi tuần (hành trình của quân mã) là bài toán về việc di chuyển một

quân mã trên bàn cờ vua (8 x 8) Quân mã được đặt ở một ô trên một bàn cờ trống

nó phải di chuyển theo quy tắc của cờ vua để đi qua mỗi ô trên bàn cờ đúng một lần Hãy viết chương trình đặt quân mã vào một vị trí bất kỳ trên bàn cờ Tìm chu trình của quân mã để ghé thăm một lần duy nhất tất cả các ô còn lại

- Quy tắc di chuyển của quân mã trên bàn cờ vua: quân mã đi theo hình chữ L

2.2 Phân tích bài toán:

Có rất nhiều lời giải cho bài toán này, chính xác là 26.534.728.821.064 lời giải trong đó quân mã có thể kết thúc tại chính ô mà nó khởi đầu Một hành trình như vật được gọi là hành trình đóng

Có những hành trình, trong đó quân mã sau khi đi hết tất cả 64 ô của bàn cờ (kể cả ô xuất phát), thì từ ô cuối của hành trình không thể đi về ô xuất phát chỉ bằng một nước đi Những hành trình như vậy được gọi là hành trình mở

Đối với bài toán mã đi tuần ta nhận thấy rằng, ban đầu tọa độ của quân mã là (i,j) bất kỳ trên bàn cờ Tại vị trí này theo quy luật di chuyển của quân mã trên bàn

cờ thì quân mã có tối đa 8 hướng đi tiếp theo Rõ ràng để đi đến các lời giải ta phải thử tất cả các trường hợp quân mã có thể đi đến ở bước 1 Với mỗi vị trí thử như vậy ta lại thử tất cả các các trường hợp của quân mã có thể đi đến ở bước 2,…

Trang 5

Cứ tiếp tục như vậy cho đến khi quân mã đi qua tất cả các ô trên bàn cờ vua thì dừng lại Như vậy, tính chất đệ quy của bài toán đó thể hiện trong các phép thử hướng đi của quân mã ở trên.

Kết quả ta tìm được nhiều chu trình đi khác nhau nhưng số bước đi đều là 63

Sử dụng giải thuật đệ quy quay lui cho bài toán mã đi tuần, ta có:

- Try(k,i,j): Chọn thực hiện bước đi thứ k, với ô xuất phát là (i,j);

- Các phương án chọn: Có 8 phương án (tương ứng với 8 trường hợp có

thể đi đến của quân mã):

Khi đó: phương án m là di chuyển mã đến ô (i+d[m], j+c[m])

- Chọn được: nếu như ô (i+d[m], j+c[m]) quân mã chưa đi qua và 1<=

i+d[m]<=8 và 1<=j+c[m]<= 8

- Thực hiện bước đi thứ k:

+ Tổ chức lưu trữ: Dùng mảng 2 chiều A có kích thước 8x8: A[1 8,

1 8] A[i,j] = 0 : nếu quân mã chưa đi qua ô (i,j)

k : nếu quân mã đã đi qua ô (i,j) ở bước thứ k

+ Lưu vết: A([i+d[m], j+c[m]):=k.

- Thành công: k=64 (hoặc k>63).

- Thông báo kết quả: In mảng A.

- Lời gọi đệ quy tiếp theo: Try(k+1, i+d[m], j+c[m]).

Trang 6

- Hủy bước đi thứ k: A([i+d[m], j+c[m]):=0.

* Thủ tục đệ quy quay lui cho nài toán này được viết như sau:

Trang 7

var x, y:integer; Begin

Trang 8

* Chạy thử chương trình: Dưới đây là một đường đi của quân mã:

3 Ứng dụng quay lui để giải một số bài toán xử lý trên mảng hai chiều

3.1 Ứng dụng quay lui để giải một số bài toán xử lý trên mảng hai chiều kích thước NxN.

3.1.1 Kiểm tra có đường đi giữa 2 đỉnh của đồ thị

a, Đề bài: Sơ đồ đường đi giữa N điểm (có số hiệu 1, 2, …, N) trong thành phố X

được cho bởi ma trận A kích thước NxN Mỗi phần tử của ma trận A chỉ có thể là 0 hoặc 1 Nếu phần tử ở hàng i, cột j của A bằng 1 thì có đường đi từ địa điểm i tới địa điểm j, ngược lại nếu không có đường đi (1≤i,j≤N)

Hãy kiểm tra giữa hai địa điểm P, Q có đường đi hay không

Dữ liệu vào là tệp văn bản LIENTHONG.INP có cấu trúc:

- Dòng đầu tiên ghi số N (0<N≤100)

- N dòng tiếp theo, mỗi dòng gồm N số là các giá trị của ma trận A

- Dòng cuối cùng ghi 2 địa điểm P, Q Các số cách nhau ít nhất một ký tự trống

Dữ liệu ra là tệp LIENTHONG.OUT ghi dòng thông báo “Co duong di:” cùng với đường đi đầu tiên tìm được đi nối từ P sang Q hoặc dòng thông báo “Khong co

duong di”

Trang 9

Ví dụ:

Tệp LIENTHONG.INP Tệp LIENTHONG.OUT 4

Để tìm đường đi từ P sang Q thì ta bắt đầu từ việc tìm đường đi từ P tới các điểm j

có đường nối trực tiếp với P, tức là A[p,j]=1 và chưa được xét (cx[j]=true) thì ta đánh dấu là j đã được kết nạp Nếu điểm j vừa kết nạp chính là Q thì thông báo có đường đi và kết thúc việc tìm kiếm, ngược lại thì thử với điểm j vừa được kết nạp Lặp lại quá trình trên cho tới khi tất cả các đỉnh đã được xét tới Vì bài toán này chỉ cần kiểm tra có đường đi từ điểm P sang Q nên ta không cần trả lại trạng thái cho đỉnh vừa được kết nạp

Nếu sau khi quá trình lặp kết thúc, ta xét cx[Q] = True thì chứng tỏ không có đường đi từ P sang Q

c, Chương trình:

PROGRAM KIEM_TRA_LIEN_THONG_GIUA_2_DINH_P_Q_QUAY_LUI;

const fi='LIENTHONG.INP'; fo='LIENTHONG.OUT';

var x:array[1 100] of integer;

a:array[1 100,1 100] of integer;

N,K,I,j,p,q,dem:INTEGER;

Cx:array[1 100] of BOOLEAN;

f:text;

Trang 10

{ -Thu tuc doc du lieu -}

write(F,'Co duong di:');

for i:=1 to dem-1 do write(f,x[i], '->');

for j:=1 to n do {xét các địa điểm của thành phố}

if (a[d,j]=1) and (cx[j]) then {nếu có đường đi từ d sang j và điểm

j chưa xét}

begin

cx[j]:=false; dem:=dem+1;

x[dem]:=j;

{nếu điểm j vừa xét chính là điếm cuối Q thì in kết quả và kết thúc}

if j=Q then begin inkq ; exit; end

else try(j,c); {ngược lại thì xét giữa điểm j và điểm cuối có

đường nối không}

Trang 11

3.1.2 Kiểm tra tính liên thông giữa nhiều cặp đỉnh của đồ thị

a, Đề bài: Sơ đồ đường đi giữa N điểm (có số hiệu 1, 2, …, N) trong thành phố X

được cho bởi ma trận A kích thước NxN Mỗi phần tử của ma trận A chỉ có thể là 0 hoặc 1 Nếu phần tử ở hàng i, cột j của A bằng 1 thì có đường đi từ địa điểm i tới địa điểm j, ngược lại nếu không có đường đi (1≤i,j≤N)

Hãy kiểm tra giữa hai địa điểm P, Q có đường đi hay không

Dữ liệu vào là tệp văn bản LTN.INP có cấu trúc:

- Dòng đầu tiên ghi số N (0<N≤100)

- N dòng tiếp theo, mỗi dòng gồm N số là các giá trị của ma trận A

- Các dòng tiếp theo mỗi dòng ghi 2 địa điểm P, Q bất kỳ

Trang 12

b, Phân tích

Đối với bài này không chỉ có một cặp địa điểm nên việc đọc và ghi dữ liệu phải thực hiện đồng thời

Thủ tục Try (d,c) hoàn toàn tương tự bài 3.1.

Trong thủ tục Doc_xuly cần lưu ý điểm sau:

- Mỗi lần đọc cặp địa điểm thì thực hiện thủ tục Try(d,c), sau khi xét có đường đi giữa 2 địa điểm vừa xét thì cần trả về trạng thái khởi tạo cho mảng đánh dấu cx để

xét tiếp cho các cặp địa điểm tiếp theo

Trang 13

FOR I:=1 TO N DO Cx[I]:=TRUE;

WHILE NOT EOF(F) DO

a, Đề bài: Tương tự bài 3.1 nhưng yêu cầu là liệt kê tất cả các đường đi khác

nhau giữa hai đỉnh P và Q trong thành phố X Số hiệu mỗi địa điểm xuất hiện không quá một lần

Trang 14

Ví dụ:

Tệp DUONG.INP Tệp DUONG.OUT 4

b, Phân tích: Tương tự bài 3.1 nhưng có 3 điểm cần bổ sung:

- Để tìm hết tất cả các đường đi thì cần trả lại trạng thái cho điểm vừa kết nạp để tiến tới việc xét các điểm khác nhằm tìm ra con đường đi mới

- Cần có một biến ktra lưu kết quả có đường đi hay không phục vụ cho việc in ấn kết quả (Vì mỗi lần ta lại trả lại trạng thái cho điểm mới kết nạp nên cx[Q] cuối cũng vẫn là True)

- Trong thủ tục in kết quả cần sử dụng thủ tục append để ghi dữ liệu.

c, Chương trình:

PROGRAM LIET_KE_DUONG_DI_GIUA_2_DINH_P_Q;

const fi='DUONG.INP'; fo='DUONG.OUT';

var x:array[1 100] of integer;

Trang 15

write(F,'Co duong di:');

for i:=1 to dem-1 do write(f,x[i], '->');

Trang 16

write(f,'Khong co duong di');close(f);

end;

END.

3.2 Ứng dụng quay lui để giải một số bài toán xử lý trên mảng hai chiều kích thước MxN.

3.2.1 Đếm số miền liên thông, miền liên thông lớn nhất.

a, Đề bài: Cho ma trận A cấp MxN, trên mỗi ô A[i,j] của lưới ghi số 0 hoặc 1

Hai ô được gọi là liên thông trực tiếp nếu nó chung cạnh và cùng giá trị 1, ngược lại

có giá trị 0 Hãy cho biết lưới ô vuông có bao nhiêu miền liên thông và miền liên thông nào là lớn nhất (có nhiều ô có giá trị 1 nhất) cùng với chỉ số của các ô đó

Dữ liệu vào: Tệp văn bản DTLT.INP có dạng:

- Dòng đầu tiên gồm 2 số M, N

- M dòng tiếp theo mỗi dòng ghi N số 0 hoặc 1

Dữ liệu ra: Tệp văn bản DTLN.OUT có dạng:

- Dòng đầu tiên ghi số liên thông

- Dòng tiếp theo ghi dòng thông báo diện tích vùng liên thông lớn nhất

- Các dòng tiếp theo ghi các vị trí của các ô thuộc vùng liên thông lớn nhất.Mỗi số phân cách nhau ít nhất một ký tự trống

Trang 17

dx:array[1 4] of integer=(-1,1,0,0);

dy:array[1 4] of integer=(0,0,1,-1); {Trên,dưới,phải,trái}

Ta sẽ xét tất cả các ô có trong lưới MxN nếu có giá trị là 1 và chưa được xét thì ghi nhận có một miền liên thông Để xác định ô đã được xét hay chưa ta dùng một mảng hai chiều b Ban đầu cho b toàn số 0 Sau khi thực hiện việc kiểm tra tại ô a[i,j] nào đó, nếu nó thuộc miền liên thông nào thì sẽ xác định lại giá trị ô b[i,j] bằng chính chỉ số miền liên thông vừa tìm được, đồng thời tăng diện tích miền liên thông

(biến dem) lên 1 đơn vị

Với mỗi miền liên thông ta so sánh với giá trị max, nếu số ô trong miền liên thông

vừa tìm lớn hơn max thì ta gán giá trị của biến dem cho max, chỉ số miền liên thông lớn nhất csmax chính bằng solt Từ ô này ta xét các ô khác xung quanh chưa được

xét và có giá trị bằng 1 để kết nạp ô đó vào miền liên thông vừa xác định được Lặp lại việc này cho tới khi hết các ô trong luới

dy:array[1 4] of integer=(0,0,1,-1); {Len,xuong,phai,trai}

VAR a,b:array[0 maxM+1,0 maxM+1] of byte;

Trang 18

for i:=1 to 4 do {xet 4 vi tri xung quanh diem (r,c)}

if (a[r+dx[i],c+dy[i]]=1) and (b[r+dx[i],c+dy[i]]=0) then

Trang 19

writeln(F,'So lien thong:',solt);

writeln(F,'Vung lien thong co dien tich lon nhat=',max);

writeln(F,'Tai cac vi tri:');

Trang 20

phát sóng nào đó nằm trên hai mảnh đất ô vuông có cùng một vùng phát sóng tại một thời điểm phát sóng nào đó hay không có ý nghĩa cho việc lên kế hoạch phát sóng trong lần phát sóng kế tiếp.

Cho trước vị trí của hai mảnh đất ô vuông, hãy xác định hai mảnh đất đó có cùng một vùng phát sóng tại một thời điểm phát sóng nào đó hay không?

Dữ liệu vào là tệp văn bản TSPS.INP có cấu trúc:

− Dòng đầu tiên ghi 2 số M, N (1≤M≤100, 1≤N≤100)

− M dòng tiếp theo, mỗi dòng ghi N ký tự ‘A’ hoặc ‘B’ nếu máy phát sóng đặt trên mảnh đất ô vuông tương ứng phát sóng loại sóng có dải tần số A hoặc B trong một lần phát sóng

− Các dòng tiếp theo, mỗi dòng ghi 4 số mô tả vị trí của hai mảnh đất ô vuông

mà ta cần kiểm tra chúng có cùng một vùng phát sóng hoặc không 2 số đầu ghi thứ tự dòng và số thứ tự cột của mảnh đất ô vuông thứ nhất, 2 số sau là thứ tự dòng và số thứ tự cột của mảnh đất ô vuông thứ hai

− Các ký tự trên cùng một dòng được ghi liên tiếp nhau Các số trên cùng một dòng được ghi cách nhau ít nhất một ký tự trống

Dữ liệu ra là tệp TSPS.OUT có số dòng là số cặp mảnh đất ô vuông mà ta cần kiểm tra xem chúng có cùng một vùng phát sóng hay không? Mỗi dòng ghi một số

là số 1 hoặc là số 0 nếu cặp mảnh đất ô vuông tương ứng có cùng một vùng phát sóng hay không

Ví dụ:

Tệp TSPS.INP Tệp TSPS.OUT

4 6 AABBAA BAABAA BBAABB AABBBB

1 2 3 4

2 3 1 6

1 0

b, Phân tích

Trang 21

Bài toán này giải quyết hoàn toàn tương tự như bài 3.1.2 – Kiểm tra tính liên thông giữa nhiều cặp đỉnh của đồ thị Ở đây chỉ khác là ma trận kích thước MxN nên thủ tục Try phải bổ sung các tham số là chỉ số dòng và cột của hai điểm.

dy:array[1 4] of integer=(0,0,1,-1); {Len,xuong,phai,trai}

VAR a:array[0 maxM+1,0 maxM+1] of CHAR;

for i:=1 to 4 do {xet 4 vi tri xung quanh diem (X1,Y1)}

if (a[X1+dx[i],Y1+dy[i]]=a[X1,Y1]) and (CX[X1+dx[i],Y1+dy[i]])

Ngày đăng: 13/10/2015, 00:01

TỪ KHÓA LIÊN QUAN

w