hướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên webhướng dẫn đăng bài lên web
THUẬT TỐN LÙA BỊ VÀO CHUỒNG Nguyễn Văn Tường Trong kỹ thuật lập trình, tốn có liên quan đến đếm đối tượng gần gũi dễ giải tính dễ xây dựng thuật tốn cho Tuy nhiên, tốn ″đếm″ thường yêu cầu với liệu lớn Nếu tổ chức liệu thuật toán hiệu khó đưa lời giải Một cách tiếp cận để xử lý tượng sử dụng thuật tốn ″lùa bò vào chuồng″ Tư tưởng thuật toán xây dựng dựa suy nghĩ thực tế để đếm số lượng bò vùng xác định người ta phải tìm cách lùa chúng vào chuồng (để chúng khỏi chạy rông) cho dễ đếm Đương nhiên bò loại phải lùa vào chuồng để dễ phân biệt lùa vào chuồng tốt Tương tự vậy, muốn giải toán đếm đối tượng ta dùng cấu trúc liệu hợp lý (thường mảng tĩnh hay mảng động) với ý nghĩa giống ″chuồng″ để lưu đối tượng, phần tử mảng tương ứng với chuồng Trên sở ta dễ dàng thực mục đích thực thao tác đếm Để hiểu thuật tốn ta xét ví dụ sau: ″Hãy đếm cho biết số lần xuất chữ La tinh file văn Giả sử văn viết toàn chữ hoa″ Rõ ràng với tốn ta duyệt toàn file lần duyệt ta thực thao tác đếm chữ Sau 26 lần duyệt tương ứng với 26 chữ ta thu tồn kết Tuy nhiên, việc duyệt file tương đối chậm file văn cho dài nên thời gian không chấp nhận Ta vận dụng thuật toán cách sử dụng mảng tĩnh A:array[′A′ ′Z′] of Longint với ý nghĩa sau: giá trị A[c] c thuộc [′A′ ′Z′] lưu số lần xuất ký tự c file văn Mảng A khởi tạo với tất giá trị 0, duyệt file ta đọc ký tự file biến trung gian ch đó, tăng giá trị mảng vị trí tương ứng có số ch lên đơn vị qua câu lệnh: A[ch]:=A[ch]+1 Như vậy, toán giải với lần duyệt file Sau khảo sát số ví dụ điển hình vận dụng thuật tốn Bài Tần số (Đề thi Olimpic sinh viên 2001, khối đồng đội) Cho văn gồm khơng q N (N ≤500) dòng, dòng chứa khơng q 80 ký tự Ta gọi tần số ký tự văn số lần xuất ký tự văn Yêu cầu: Tìm tần số lớn tần số chữ (không phân biệt chữ hoa hay chữ thường) văn cho Dữ liệu vào: từ file văn có tên FREQ.INP: Dòng chứa N số lượng dòng văn N dòng dòng chứa dòng văn cho Kết quả: ghi file văn có tên FREQ.OUT tần số lớn tìm Ví dụ: FREQ.INP faculty of technology Hanoi National University aaAAAAAaaaaAAAAaAaAaAa cccCCCeeefffggg123456$#)(*+= FREQ.OUT 25 Lời giải cho toán gần giống ví dụ trình bày Bạn đọc xem thuật giải thơng qua chương trình mẫu đây: var a:array[1 256] of longint; n:integer; procedure solve; var f:text;i,j,k:integer; s:string; ss:set of byte; begin fillchar(a,sizeof(a),0); ss:=[65 90]; assign(f,′FREQ.INP′); reset(f); readln(f,n); for i:=1 to n begin readln(f,s); for j:=1 to length(s) begin k:=ord(s[j]); if k in ss then k:=k+32; inc(a[k]); end; end; close(f); end; procedure output; var f:text; i,m:longint; begin assign(f,′FREQ.OUT′); Rewrite(f); m:=a[1]; for i:=2 to 256 if m < a[i] then m:=a[i]; write(f,m); close(f); end; begin solve; output; end Bài Phủ nhỏ (Đề thi chọn học sinh giỏi Quốc gia lớp 12 năm 1998-1999) Cho tập hợp n đoạn thẳng (đánh số từ đến n) với đầu mút có toạ độ nguyên [Li,Ri], i=1,2, 3,…,n đoạn thẳng [P,Q] (P, Q số nguyên) Yêu cầu: Cần tìm số đoạn thẳng tập cho để phủ kín đoạn thẳng [P,Q] (nghĩa điểm x thuộc [P,Q] phải thuộc vào số đoạn thẳng chọn) Dữ liệu vào: từ file văn PHU.INP: - Dòng ghi số n, P, Q phân cách dấu trắng; - Dòng thứ i số n dòng chứa hai số L, R phân cách dấu trắng (i=1, 2,…, n); ≤ n ≤ 100 000; P − Q ≤5000; |Li| ≤ 50000; |Ri|≤50000, i = 1, 2,…, n Kết quả: ghi file văn PHU.OUT: - Dòng ghi số k số lượng đoạn cần chọn (quy ước ghi số khơng tìm lời giải); - Nếu k > dòng số k dòng ghi số đoạn thẳng chọn Ví dụ: Thuật tốn: Ta phân tích tốn để áp dụng sáng tạo tư tưởng thuật tốn trình bày sau: Ta thấy độ dài đoạn thẳng [P,Q] khơng lớn 5000 Còn số đoạn thẳng tập cho lên tới 100000 Ta lưu tất đoạn thẳng lại Vậy lưu đoạn thẳng theo cách: lưu đoạn một, dùng mảng A có độ dài độ dài đoạn thẳng [P,Q], kích thước mảng 5000x2 (A: Array [ 5000, ] Of LongInt;) Ta coi đoạn [P,Q] mảng A Ta đọc đoạn thẳng tập n đoạn thẳng Với đoạn thẳng vừa đọc được, ta xét xem chúng phủ đoạn [P,Q] đâu độ dài mà đoạn thẳng phủ Ta lưu lại mảng A phần tử mà đoạn thẳng vừa đọc bắt đầu phủ đoạn [P,Q] số đoạn thẳng độ dài chúng phủ A[Phần tử bắt đầu phủ,1] = số đoạn vừa đọc A[Phần tử bắt đầu phủ, 2] = độ dài mà đoạn phủ Nếu có nhiều đoạn thẳng bắt đầu phủ đoạn [P,Q] vị trí chọn đoạn có độ dài phủ lớn Sau làm xong công việc ta mảng gồm đoạn thẳng phủ lên đoạn [P,Q] Bây ta tiến hành tìm xem số đoạn phủ cách: ta bắt đầu từ vị trí (nếu vị trí mà khơng có đoạn phủ khơng có lời giải) ta tìm xem có đoạn giao với đoạn mà tạo thành đoạn thẳng có phủ dài ta lưu đoạn lại (nếu khơng có đoạn thẳng giao với đoạn thẳng để tạo đoạn thẳng có độ che phủ lớn độ che phủ đoạn khơng có lời giải) Làm tương tự với đoạn thẳng vừa tìm đoạn thẳng chọn phủ kín đoạn [P,Q] ta số đoạn thẳng để phủ đoạn [P,Q] Như vậy, thuật toán cho phép giải toán với lần duyệt mảng Dưới chương trình minh hoạ: Const Fi = ′PHU.INP′; Fo = ′PHU.OUT′; Max = 5000; Dd = 2; Type Vec1 = Array [ Max,1 ] Of LongInt; Vec2=Array[0 Max] Of LongInt; Var n, P, Q, Min,Id : LongInt; A : Vec1; Chon : Vec2; Procedure InitData; Var i, L, R : LongInt; F : Text; Begin Id:=1; Assign(F, Fi); Reset(F); Readln(F,n,P,Q); FillChar(A, SizeOf(A),0); For i := To n Do Begin Readln(F,L,R); If L Q Then A[0, Dd] := Q - P Else A[0, Dd] := R - P; End Else Else If L Q Then A[L - P, Dd] := Q - L Else A[L - P, Dd] := R - L; End; End; Close(F); End; Function tt(u,v:LongInt):LongInt; Begin If A[u, Dd]+uMax) Then Begin Max:=tt(i,j); tmp:=i; End; If Max=j+A[j,Dd] Then Exit Else Begin Count:=Count + 1; Chon[Count]:=A[tmp, id]; j :=tmp; If Max = Q - P Then Dung := True; End; End; Min := Count; End; Procedure ReSult; Var F : Text; i : LongInt; Begin Assign(F, FO); ReWrite(F); Writeln(F, Min); If Min Then For i: = To Min Do Writeln(F, Chon[i]); Close(F); End; Begin InitData; solve; ReSult; End Bài tập Các số lặp Cho dãy số nguyên gồm N phần tử Lập chương trình in số nguyên lặp nhiều dãy (N