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

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

Đ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

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. 1 − 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 2 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; 3 End; - 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,… 4 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ã): + Kí hiệu phương án: m = 1, 2, …, 8. + Thiết lập hai mảng một chiều d,c lưu trữ tọa độ tương ứng 8 khả năng di chuyển của quân mã: d -1 1 2 2 1 -1 -2 -2 Chỉ số m 1 2 3 4 5 6 7 8 c -2 -2 -1 1 2 2 1 -1 Chỉ số m 1 2 3 4 5 6 7 8 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à 14->3 1->4->3 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; a:array[1..100,1..100] of integer; N,K,I,j,p,q,dem:INTEGER; Cx:array[1..100] of BOOLEAN; f:text;Ktra:boolean; {---------Thu tuc doc du lieu---------} procedure doc; var i,j:integer; begin assign(f,fi);reset(f); readln(f,n); for i:=1 to n do begin for j:=1 to n do read(f,a[i,j]); readln(f); end; read(f,p,q); 14 close(f); end; {---------Thu tuc in ket qua---------} procedure inkq; var i:integer;f:text; begin Assign(f,fo); Append(f); write(F,'Co duong di:'); for i:=1 to dem-1 do write(f,x[i], '->'); Writeln(f,X[dem]); close(f); end; {---------Thu tuc try---------} procedure try(d,c:integer); var j:integer; begin for j:=1 to n do if (a[d,j]=1) and (cx[j]) then begin cx[j]:=false; dem:=dem+1; x[dem]:=j; if j=Q then begin ktra:=true; inkq ; end else try(j,c); dem:=dem-1; cx[j]:=true; end; end; BEGIN doc; {Khoi tao} FOR I:=1 TO N DO Cx[I]:=TRUE; dem:=1; cx[P]:=false;x[dem]:=P; ktra:=false; {ban dau cho rang khong co duong di} Try(P,Q); if ktra=false then begin assign(f,fo);rewrite(f); 15 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 Ví dụ: Tệp DTLT.INP 44 1100 0110 0011 1100 Tệp DTLT.OUT So lien thong:2 Vung lien thong dien tich lon nhat=6 Tai cac vi tri: 11 12 22 23 33 34 b, Phân tích Ta thấy rằng mỗi một ô tại vị trí [i,j] có thể liên thông với 4 ô xung quanh (Trên, dưới, phải, trái) của nó. Vì thế sử dụng 2 hằng mảng một chiều thể hiện độ biến thiên của hàng, cột: 16 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. Lưu ý: - Ta phải làm công việc bao quanh lưới MxN một loạt các số 0 để các ô ở biên của lưới cũng xét tương tự như các ô khác. - Để biết được ô [i,j] nào đó thuộc miền liên thông nào ta căn cứ vào mảng b để xác định được miền liên thông nào là lớn nhất cùng vị trí các ô trong miền. c, Chương trình program VUNG_LIEN_THONG_LON_NHAT; uses crt; const fi='DTLT.INP';fo='DTLT.OUT';maxM=50; dx:array[1..4] of integer=(-1,1,0,0); 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; solt,m,n,k,h,dem,csMAX,max:integer; f:text; {---------Thu tuc doc du lieu---------} PROCEDURE DOCTEP; var i,j:integer; 17 begin assign(f,fi);reset(f); readln(f,m,n); fillchar(a,sizeof(a),0); {Tao mang a toan so 0} for i:=1 to m do begin for j:=1 to n do read(f,a[i,j]); readln(f); end; close(f); end; {---------Thu tuc try---------} PROCEDURE Try(r,c:integer); var i:integer; begin 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 begin dem:=dem+1; b[r+dx[i],c+dy[i]]:=solt; try(r+dx[i],c+dy[i]); end; end; {---------Thu tuc xu ly---------} PROCEDURE XULY; var h,k:integer; begin solt:=0; for k:=1 to m do for h:=1 to n do begin if (a[k,h]=1) and (b[k,h]=0) then begin solt:=solt+1; b[k,h]:=solt; dem:=1; try(k,h); IF dem>MAX THEN begin max:=dem;csMAX:=solt;end; end; end; 18 end; {---------Thu tuc in ket qua---------} PROCEDURE INKQ; var i,j:integer; Begin assign(f,fo);rewrite(f); writeln(F,'So lien thong:',solt); writeln(F,'Vung lien thong co dien tich lon nhat=',max); writeln(F,'Tai cac vi tri:'); FOR I:=1 TO M DO FOR J:=1 TO N DO IF B[I,J]=csMAX THEN WRITELN(F,I,' ',J); close(f); end; BEGIN clrscr;DOCTEP; fillchar(b,sizeof(b),0); max:=0; XULY; INKQ; END. 3.2.2. Bài toán tần số phát sóng: (Bài 3 - Đề thi chọn HSG Tin 12 năm học 2013 – 2014) Người ta phân hoạch một vùng đất hình chữ nhật thành MxN ô vuông bởi các đường kẻ song song với các đường biên của vùng đất đó. Vị trí của mỗi mảnh đất ô vuông được xác định bởi cặp số (x, y) trong đó x là số thứ tự dòng tính từ trên xuống dưới, y là thứ tự cột tính từ trái sang phải của mảnh đất ô vuông đó khi ta nhìn từ một mặt phẳng song song phía trên mặt phẳng vùng đất. Tại mỗi ô vuông của vùng đất được đặt một máy phát sóng vô tuyến điện tử. Mỗi ngày có thể phát ra các loại sóng có dải tần A hoặc B; tại mỗi thời điểm phát sóng chỉ phát ra mỗi loại sóng có một dải tần số nào đó mà thôi. Ta có thể di chuyển từ vị trí máy phát sóng này đến vị trí máy phát sóng khác nếu hai máy phát sóng đó nằm trên hai mảnh đất ô vuông có cạnh chung. Một vùng máy phát sóng là tập hợp các mảnh đất ô vuông có trên đó đặt các máy phát sóng phát ra loại sóng có cùng dãy tần số. Việc xác định hai máy 19 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 46 AABBAA BAABAA BBAABB AABBBB 1234 2316 Tệp TSPS.OUT 1 0 b, Phân tích 20 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. c, Chương trình program Bai_3_HSG12_2013_2014; uses crt; const fi='TSPS.INP';fo='TSPS.OUT';maxM=100; dx:array[1..4] of integer=(-1,1,0,0); 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; CX:array[0..maxM+1,0..maxM+1] of boolean; m,n,p,q,k,h:integer; f,g:text; {---------Thu tuc try---------} PROCEDURE TRY(X1,Y1,X2,Y2:integer); var i:integer; begin 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]]) then begin CX[X1+dx[i],Y1+dy[i]]:=FALSE; IF (X1+dx[i]=X2) AND (Y1+dy[i]=Y2) THEN BEGIN ASSIGN(G,Fo);append(g); WRITELN(G,'1'); CLOSE(G); END ELSE TRY(X1+dx[i],Y1+dy[i],X2,Y2); end; end; {---------Thu tuc vua doc va xu ly---------} Procedure doc_XULY; var i,j:integer; begin 21 assign(f,fi);reset(f); readln(f,M,n); fillchar(a,sizeof(a),0); {Tao mang a toan so 0} for i:=1 to M do begin for j:=1 to N do read(f,a[i,j]); readln(f); end; FILLCHAR(CX,SIZEOF(CX),TRUE); WHILE NOT EOF(F) DO BEGIN readln(f,p,q,K,H); cx[p,Q]:=false; TRY(P,Q,K,H); if cx[K,H] then begin assign(g,fo); append(g); writeln(G,'0');close(g);end; FILLCHAR(CX,SIZEOF(CX),TRUE); {sua lai trang thai ban dau cho mang cx} END; close(f); end; BEGIN clrscr; doc_XULY; END. 3.2.3. Trò chơi Sukudo Sukudo là trò chơi đã thịnh hành từ lâu và rất phổ biến. Sudoku là một loại trò chơi lôgic và cách chơi là điền số từ 1 đến 9 vào những ô trống sao cho mỗi cột dọc, mỗi hàng ngang, mỗi phân vùng nhỏ (ô 3x3) có đủ các số từ 1 đến 9 mà không được lặp lại. Bảng câu đố hình vuông, mỗi chiều có 9 ô nhỏ, hợp thành 9 cột, 9 hàng và được chia thành 9 ô lớn 3x3. Một vài ô nhỏ được đánh số, đó là những manh mối duy nhất để bạn tìm lời giải. Tuỳ theo mức độ nhiều hay ít của các manh mối, các câu đố được xếp loại dễ, trung bình, khó hay cực khó. Ngoài ra, còn những bảng như 16x16, 25x25 hay thậm chí 100x100. 22 3 6 4 1 9 2 8 7 5 1 5 9 7 8 3 2 6 4 2 8 7 4 5 6 9 1 3 6 9 1 2 4 5 7 3 8 8 2 5 3 7 1 4 9 6 7 4 3 8 6 9 5 2 1 4 1 2 5 3 7 6 8 9 9 3 8 6 2 4 1 5 7 5 7 6 9 1 8 3 4 2 Một ví dụ về trò chơi Sudoku Ở đây tôi muốn đề cập tới việc giải SUKUDO kích thước 9x9 ở mức độ dễ bằng quay lui. Để giải trò chơi này ta cần có: - Mảng a: lưu bảng khởi tạo ban đầu. - Mảng ah: ah[i,j]=true, nếu số j đã có trong hàng i, ngược lại ah[i,j]=false - Mảng ac: ac[i,j]=true, nếu số j đã có trong cột i, ngược lại ac[i,j]=false - Mảng 3 chiều ac: dùng để lưu việc kiểm tra số i nào đó thuộc vùng kích thước (3x3) nào. Nếu đã có trong vùng đó thì av[xv,yv, i] nhận giá trị true, ngược lại nhận giá trị false. Trong khi đọc dữ liệu từ tệp văn bản chứa dữ liệu vào là bảng trò chơi ban đầu, nếu giá trị tại ô nào đó khác 0 thì ta xác định lại trạng thái của các ô trong ma trận ah, ac và av. Việc xác định số a[i,j] nào đó thuộc phân vùng (3x3) dựa vào công thức: xv:=((i-1)div 3)+1; yv:=((j-1)div 3)+1; Trong đó xv là chỉ số dòng của vùng, yv là chỉ số cột của vùng (1≤xv, yv≤3). Thủ tục Try(x,y,stop) : Sẽ thử đặt lần lượt các số từ 1 - 9 vào ô ở hàng x, cột y, nếu vẫn còn ô trống - ô chưa được đặt số nào. 23 - Tìm ô trống đầu tiên, xác định ô đó thuộc phân vùng (3x3) nào bằng công thức ở trên. - Duyệt các số i chạy từ 1 – 9 nếu số đó chưa thuộc hàng x, chưa thuộc cột y và phân vùng (xv, yv) thì ghi nhận thử số i này vào ô trống đó. - Nếu ô trống này là ô cuối cùng của cột cuối, hàng cuối thì kết thúc việc điền các giá trị. Ngược lại chưa phải hàng cuối thì gọi thủ tục Try cho ô ở cột đầu tiên của dòng tiếp theo tức là Try(x+1,1,stop), chưa phải là cột cuối thì gọi thủ tục Try cho vị trí ô kế tiếp cùng hàng tức là Try(x,y+1,stop) . - Lặp đi lặp lại quá trình trên với các ô trống mới, nếu chưa giải ra thì quay lui để điền lại các khả năng khác. Đồng thời đánh dấu lại trạng thái ở các mảng a, ah, ac và av. Cài đặt chương trình: program sudoku; uses crt; var a:array[1..9,1..9] of byte; ah,ac:array[1..9,1..9] of boolean; av:array[1..3,1..3,1..9] of boolean; stop:boolean; {----------------------------------------} procedure DOCTEP; var f:text; i,j,xv,yv,k:byte; begin assign(f,'sudoku.inp'); reset(f); for i:=1 to 9 do for j:=1 to 9 do begin read(f,a[i,j]); if a[i,j]0 then begin xv:=((i-1)div 3)+1; yv:=((j-1)div 3)+1; 24 ah[i,a[i,j]]:=true; {so a[i,j] da co trong hang i} ac[j,a[i,j]]:=true; {so a[i,j] da co trong cot j} av[xv,yv,a[i,j]]:=true; {so a[i,j] da co trong phan vung (3x3) xc,yc} end; end; close(f); end; {----------------------------------------} Procedure INKQ; var i,j:byte; f:text; begin assign(f,'sudoku.out');rewrite(f); for i:=1 to 9 do begin for j:=1 to 9 do write(f,a[i,j],' '); writeln(f); end; close(f); end; {----------------------------------------} Procedure Try(x,y:byte;var stop:boolean); var i,xv,yv:byte; ktra:boolean; begin if a[x,y]0 then begin repeat inc(y); {thu cot ke ben} if y=10 then begin {xuong hang ke tiep} y:=1; inc(x); end; stop:=x=10; until(a[x,y]=0)or(stop); if not(stop) then try(x,y,stop); 25 end else begin xv:=((x-1)div 3)+1; yv:=((y-1)div 3)+1; {xét các chữ số từ 1 tới 9} for i:=1 to 9 do if not(stop) then begin {số đó chưa có trong hàng x, cột y, vùng (xv,yv)} ktra:=(ah[x,i]=false)and(ac[y,i]=false)and(av[xv,yv,i]=false); if ktra then begin a[x,y]:=i; ah[x,i]:=true; ac[y,i]:=true; av[xv,yv,i]:=true; if y=9 then if x=9 then stop:=true else try(x+1,1,stop) else try(x,y+1,stop); if (not(stop)) then begin a[x,y]:=0; ah[x,i]:=false; ac[y,i]:=false; av[xv,yv,i]:=false; end; end; end; end; end; {----------------------------------------} Begin clrscr; DOCTEP; try(1,1,stop); if stop then INKQ; readln End. 26 KẾT LUẬN Một bài toán có thể được giải quyết bằng nhiều thuật toán khác nhau. Đệ quy quay lui là một trong những phương pháp tương đối hiệu quả. Lẽ dĩ nhiên quay lui cũng có nhược điểm của nó. Đó là khi giải các bài toán với bộ dữ liệu lớn thì quay lui tốn rất nhiều thời gian và khó khăn trong việc lưu trữ. Tuy nhiên không thể phủ nhận quay lui là phương pháp giải các bài toán liệt kê khá hiệu quả và dễ hiểu đối với trình độ của học sinh THPT, đặc biệt là trong các trường THPT không chuyên. Từ những bài toán mà tôi nêu ở trên ta có thể thấy quay lui có thể giải quyết các bài toán ứng dụng nhiều trong thực tế. Trong các năm học vừa qua, tác giả đã chú tâm thực hiện việc hình thành phương pháp giải các bài toán Tin học bằng đệ quy quay lui cho một số học sinh trong đội tuyển thi học sinh giỏi Tỉnh của trường và thấy kết quả rất tốt. Tỷ lệ đạt học sinh giỏi Tỉnh từ 33,3% trong năm học 2011 – 2012, sau khi áp dụng đề tài này đã tăng lên 100% trong hai năm học 2012 – 2013 và 2013 – 2014. Học sinh hứng thú hơn với môn Tin, kỹ năng lập trình cũng được nâng cao. Do thời gian nghiên cứu còn ít, năng lực còn nhiều hạn chế nên đề tài chắc còn nhiều khiếm khuyết. Tác giả rất mong muốn nhận được nhiều góp ý chân thành từ các đồng nghiệp, các bạn đọc và các em học sinh để đề tài được hoàn thiện hơn, góp phần nâng cao chất lượng dạy học Tin học. Xin chân thành cảm ơn! 27 TÀI LIỆU THAM KHẢO ---------------------[1] Đỗ Xuân Lôi, Cấu trúc dữ liệu và giải thuật, Nhà xuất bản khoa học và kỹ thuật. [2] Hồ Sỹ Đàm (chủ biên), Tài liệu giáo khoa chuyên Tin, Nhà xuất bản giáo dục Việt Nam. [3] Lê Minh Hoàng, Giải thuật và lập trình, Đại học Sư phạm Hà Nội. [4] Nguyễn Xuân Huy, Sáng tạo trong thuật toán và lập trình - Tập 1, Nhà xuất bản giáo dục. [5] Các tài liệu về Đệ quy quay lui trên Internet. 28 MỤC LỤC 29 [...]... then begin assign(f,fo);rewrite(f); 15 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... Một bài toán có thể được giải quyết bằng nhiều thuật toán khác nhau Đệ quy quay lui là một trong những phương pháp tương đối hiệu quả Lẽ dĩ nhiên quay lui cũng có nhược điểm của nó Đó là khi giải các bài toán với bộ dữ liệu lớn thì quay lui tốn rất nhiều thời gian và khó khăn trong việc lưu trữ Tuy nhiên không thể phủ nhận quay lui là phương pháp giải các bài toán liệt kê khá hiệu quả và dễ hiểu đối... Ta có thể di chuyển từ vị trí máy phát sóng này đến vị trí máy phát sóng khác nếu hai máy phát sóng đó nằm trên hai mảnh đất ô vuông có cạnh chung Một vùng máy phát sóng là tập hợp các mảnh đất ô vuông có trên đó đặt các máy phát sóng phát ra loại sóng có cùng dãy tần số Việc xác định hai máy 19 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... Sudoku Ở đây tôi muốn đề cập tới việc giải SUKUDO kích thước 9x9 ở mức độ dễ bằng quay lui Để giải trò chơi này ta cần có: - Mảng a: lưu bảng khởi tạo ban đầu - Mảng ah: ah[i,j]=true, nếu số j đã có trong hàng i, ngược lại ah[i,j]=false - Mảng ac: ac[i,j]=true, nếu số j đã có trong cột i, ngược lại ac[i,j]=false - Mảng 3 chiều ac: dùng để lưu việc kiểm tra số i nào đó thuộc vùng kích thước (3x3) nào... ô xung quanh (Trên, dưới, phải, trái) của nó Vì thế sử dụng 2 hằng mảng một chiều thể hiện độ biến thiên của hàng, cột: 16 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... học sinh THPT, đặc biệt là trong các trường THPT không chuyên Từ những bài toán mà tôi nêu ở trên ta có thể thấy quay lui có thể giải quyết các bài toán ứng dụng nhiều trong thực tế Trong các năm học vừa qua, tác giả đã chú tâm thực hiện việc hình thành phương pháp giải các bài toán Tin học bằng đệ quy quay lui cho một số học sinh trong đội tuyển thi học sinh giỏi Tỉnh của trường và thấy kết quả rất... − 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ự... Try(x+1,1,stop), chưa phải là cột cuối thì gọi thủ tục Try cho vị trí ô kế tiếp cùng hàng tức là Try(x,y+1,stop) - Lặp đi lặp lại quá trình trên với các ô trống mới, nếu chưa giải ra thì quay lui để điền lại các khả năng khác Đồng thời đánh dấu lại trạng thái ở các mảng a, ah, ac và av Cài đặt chương trình: program sudoku; uses crt; var a:array[1 9,1 9] of byte; ah,ac:array[1 9,1 9] of boolean; av:array[1... 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... dục Việt Nam [3] Lê Minh Hoàng, Giải thuật và lập trình, Đại học Sư phạm Hà Nội [4] Nguyễn Xuân Huy, Sáng tạo trong thuật toán và lập trình - Tập 1, Nhà xuất bản giáo dục [5] Các tài liệu về Đệ quy quay lui trên Internet 28 MỤC LỤC 29 ... thử chương trình: Dưới đường quân mã: Ứng dụng quay lui để giải số toán xử lý mảng hai chiều 3.1 Ứng dụng quay lui để giải số toán xử lý mảng hai chiều kích thước NxN 3.1.1 Kiểm tra có đường đỉnh... thức đệ quy quay lui (Back tracking) Bài toán kinh điển: Mã tuần Ứng dụng quay lui để giải số toán xử lý mảng hai chiều Kết luận PHẦN II: PHẦN NỘI DUNG Nhắc lại kiến thức đệ quy quay lui (Back... đệ quy quay lui − Áp dụng giải với số toán cụ thể IV Đối tượng nghiên cứu: Đối tượng nghiên cứu đề tài đệ quy quay lui ứng dụng quay lui để giải toán Tin học có liên quan tới mảng hai chiều tài

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

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan