1. Trang chủ
  2. » Giáo án - Bài giảng

Tài liệu ôn thi HSG

7 1,1K 34
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 7
Dung lượng 49,5 KB

Nội dung

Phơng pháp đánh dấu phần tử đợc chọn Đánh dấu phần tử đợc chọn 1- ý tởngchung Kỹ thuật đánh dấu phần tử là một trong những kỹ thuật nhằm giúp cho ngời lập trình tạo đợc những thuật toán đơn giản để giải quyết vấn đề đặt ra. Để đánh dấu phần tử đợc chọn, ta khai báo một mảng A gồm nhiều phần tử, với A[i]=true theo nghĩa i là phần tử đợc chọn, A[i]=false theo nghĩa i là phần tử không đợc chọn. 2- ứng dụng PP đánh dấu trong bài toán sắp xếp dãy số Sắp xếp dữ liệu đóng vai trò rất quan trọng trong xữ lý thông tin. ý nghĩa thực tiễn của sắp xếp là nhằm dễ dàng tìm kiếm thông tin cần thiết. Bài toán: Cho một dãy số gồm N phần tử (1<=N<=32766). Các phần tử a i của dãy là các số nguyên dơng, đôi một khác nhau (1<=a i <=32766). Hãy sắp xếp dãy số tăng dần. Ta thờng sử dụng thuật giải sắp xếp đơn giản để giải quyết bài toán này nh sau: For i:=1 to N-1 do For j:=i+1 to N do If a[i]<a[j] then Begin t:=a[i]; a[i]:=a[j] a[j]:=t; End; Chơng trình biểu diễn của thuật toán: const fi='sap1.inp'; fo='sap1.out'; type mmc=array[1 32766] of integer; var f:text; i,j,n,t:integer; a:^mmc; ti:longint; begin ti:=meml[0:$46c]; new(a); assign(f,fi);reset(f); readln(f,n); for i:=1 to n do read(f,a^[i]); close(f); for i:=1 to n-1 do for j:=i+1 to n do if a^[i]>a^[j] then begin t:=a^[i]; a^[i]:=a^[j]; a^[j]:=t; end; CTT Media Phơng pháp đánh dấu phần tử đợc chọn assign(f,fo);rewrite(f); writeln(f,n); for i:=1 to n do write(f,a^[i],' '); close(f); dispose(a); writeln('Thoi gian thu hien ',(meml[0:$46c]-ti)/18.21:8:5); readln; end. Khi N bé, thuật toán trên là chấp nhận đợc. Tuy nhiên, trong nhiều trờng hợp N lớn, chẳng hạn N=32766 phần tử, khi đó độ phức tạp của thuật toán là O(N 2 ) máy sẽ thực hiện trong rất nhiều thời gian mới sắp xếp đợc dãy số. (với N=20000, thời gian thực hiện khoảng 14 giây) Để giải quyết đợc bài toán này khi N lớn trong một khoảng thời gian rất nhỏ, ta sử dụng kỹ thuật đánh dấu phần tử. Ta cần chú ý đến một giả thiết quan trọng trong bài toán đặt ra là các phần tử đôi một khác nhau, nghĩa là trong dãy không có phần tử nào trùng nhau. Đối với bài toán sắp xếp có phần tử trùng nhau ta không thể sử dụng phơng pháp này. Phơng pháp: Dữ liệu: Sử dụng một mảng A gồm 32766 phần tử, các phần tử có kiểu boolean. ý nghĩa: A[i]=true có nghĩa i là phần tử có trong dãy, A[i]=false có nghĩa i là phần tử không có trong dãy. Thuật toán: + Khởi động mọi giá trị của A[] là False {Giống nh giả sử ban đầu mọi phần tử đều không thuộc dãy số} + Đọc từng phần tử của dãy số, giả sử số thứ j của dãy là X, ta đánh dấu phần tử A[X]=true {Xác nhận số X thuộc dãy số}. Thực hiện đánh dấu cho đến khi đọc hết dãy số. Khi đó ta thu đợc một mảng A[] trong đó A[i]=true tại các chỉ số i có giá trị bằng giá trị các phần tử trong dãy số. + Duyệt từ đầu mảng đến cuối mảng, nếu vị trí vào có giá trị True thì ta xuất chỉ số đó ra. Kết quả ta đợc một dãy số đợc sắp xếp tăng dần. Chơng trình mẫu: const fi='sap1.inp'; fo='sap2.out'; type mmcb=array[1 32766] of boolean; var f:text; n:word; b:mmcb; ti:longint; procedure doc; var i,x:word; begin CTT Media Phơng pháp đánh dấu phần tử đợc chọn fillchar(b,sizeof(b),false); assign(f,fi); reset(f); readln(f,n); for i:=1 to n do begin read(f,x); b[x]:=true; end; close(f); assign(f,fo); rewrite(f); writeln(f,n); for i:=1 to 32766 do if b[i]=true then write(f,i,' '); end; begin ti:=meml[0:$46c]; doc; writeln('TG=',(meml[0:$46c]-ti)/18.21:8:4); readln; end. Nhận xét: Khi N=20000 chơng trình thực hiện trong 0.05giây. Chơng trình này chạy nhanh gấp 280 lần so với chơng trình đã viết theo thuật toán đơn giản trên. Rõ ràng, kỹ thuật đánh dấu phần tử có ý nghĩa rất quan trọng trong việc giảm thời gian thực hiện chơng trình. 3-ứng dụng PP đánh dấu trong bài toán lọc dữ liệu Lọc dữ liệu là một vấn đề có ý nghĩa to lớn trong xử lý thông tin. ý nghĩa thực tiễn của lọc dữ liệu là nhằm loại bỏ các dữ liệu d thừa, không cần thiết, từ đó dễ dàng thu đợc thông tin cần tìm. Bài toán: Cho một dãy số gồm N phần tử (1<=N<=32766), trong đó các phần tử có kiểu nguyên nằm trong [1 32766]. Hãy trích ra từ dãy số trên một tập con gồm nhiều phần tử nhất sao cho các phần tử đôi một khác nhau. Ta thờng giải quyết bài toán trên theo thuật toán đơn giản nh sau: + Dùng một mảng B[] để lu các giá trị tìm đợc + Đọc từng phần tử của dãy số đã cho, giả sử số đọc đợc là X. Kiểm tra xem X đã có trong B[] hay cha. + Nếu cha có trong B[] thì đặt vào cuối cùng của B[] Khi N bé, thuật toán trên có thể chấp nhận đợc. Tuy nhiên, trong nhiều trờng hợp N rất lớn, chẳng hạn N=32766 phần tử, khi đó độ phức tạp của thuật toán là O(N 2 ) máy sẽ thực hiện trong rất nhiều thời gian để lấy từng phần tử trong dãy để so sánh với các phần tử trong tập B[]. CTT Media Phơng pháp đánh dấu phần tử đợc chọn Để giải quyết đợc bài toán này khi N lớn trong một khoảng thời gian rất nhỏ, ta sử dụng kỹ thuật đánh dấu phần tử. Phơng pháp: Dữ liệu: Sử dụng một mảng B gồm 32766 phần tử, các phần tử có kiểu boolean. ý nghĩa: B[i]=true có nghĩa i là phần tử ta sẽ chọn, B[i]=false có nghĩa i là phần tử ta không chọn. Thuật toán: + Khởi động mọi giá trị của B[] là False {Giống nh giả sử ban đầu ta cha chọn phần tử nào cả} + Đọc từng phần tử của dãy số, giả sử số thứ j của dãy là X, ta đánh dấu phần tử B[X]=true {Xác nhận số X đợc chọn}. Thực hiện đánh dấu cho đến khi đọc hết dãy số. Khi đó ta thu đợc một mảng B[] trong đó B[i]=true tại các chỉ số i mà ít nhất i xuất hiện một lần trong dãy đã cho + Duyệt từ đầu mảng đến cuối mảng B[], nếu vị trí nào có giá trị True thì ta xuất chỉ số đó ra. Kết quả ta đợc một tập các phần tử cần tìm. Chơng trình mẫu: const fi='tc.in1'; fo='tc.ou4'; nn=60000; var n,a:word; f:text; k:array[1 nn] of boolean; procedure doctep; var i:word; begin assign(f,fi); reset(f); readln(f,n); for i:=1 to n do begin read(f,a); k[a]:=true; end; close(f); end; procedure xulivaxuat; var i,d:word; begin assign(f,fo); rewrite(f); d:=0; for i:=1 to nn do CTT Media Phơng pháp đánh dấu phần tử đợc chọn if k[i]=true then d:=d+1; writeln(f,d); for i:=1 to nn do if k[i]=true then write(f,' ',i); close(f); end; BEGIN doctep; xulivaxuat; END. Nhận xét: Chơng trình này chạy nhanh gấp khoảng 300 lần so với chơng trình đã viết theo thuật toán đơn giản trên. 4-ứng dụng PP đánh dấu trong bài toán tìm giao của hai tập hợp Xác định giao của hai tập hợp là một bài toán quan trọng trong toán học. Trong thực tiễn, phép giao nhằm giúp ta xác định đợc nhóm thông tin chung nhất của nhiều nhóm thông tin. Bài toán: Cho 2 tệp văn bản TEP1.INP và TEP2.INP chứa N số tự nhiên trong khoảng 1 M có thể trùng nhau. Hãy tạo TEP3.OUT chứa các số có mặt trong cả hai tệp TEP1.INP và TEP2.INP sao cho các số đôi một khác nhau. DLV DLR Dòng 1: Số N(1<=N<=32766) Dòng 2: N số a i (1<=a i <=M<=32766) Dòng 1 chứa các số tìm đợc Ví dụ TEP1.INP TEP2.INP TEP3.OUT 7 5 7 1 3 5 2 7 6 3 5 1 2 1 19 1 3 2 5 Ta thờng giải quyết bài toán trên theo thuật toán đơn giản nh sau: + Dùng mảng A[] để lu các số trong tệp 1 + Dùng mảng B[] để lu các số trong tệp 2 + Lấy từng phần tử X i trong A[], so sánh với lần lợt từng phần tử Y j trong B[]. Nếu X i có trong B[] thì đem X i đặt vào mảng C[]. + Lấy từng phần tử Y j trong B[], so sánh với lần lợt từng phần tử Z k trong C[]. Nếu Y j có trong C[] thì đem Y j đặt vào mảng D[]. + Xuất mảng D, ta thu đợc tập giao của hai tệp. Khi N bé, thuật toán trên có thể chấp nhận đợc. Tuy nhiên, trong nhiều trờng hợp N rất lớn, chẳng hạn N=32766 phần tử, khi đó độ phức tạp của thuật toán là O(2N 2 ) máy sẽ thực hiện trong rất nhiều thời gian để lấy từng phần tử trong A[] để so sánh với các phần tử trong B[]. Để giải quyết đợc bài toán này khi N lớn trong một khoảng thời gian rất nhỏ, ta sử dụng kỹ thuật đánh dấu phần tử nh sau: Phơng pháp: CTT Media Phơng pháp đánh dấu phần tử đợc chọn Dữ liệu: Sử dụng hai mảng A và B gồm 32766 phần tử, các phần tử có kiểu boolean. ý nghĩa: A[i]=true có nghĩa i là phần tử thuộc tệp 1, A[i]=false có nghĩa i là phần tử không thuộc tệp 1. B[i]=true có nghĩa i là phần tử thuộc tệp 2, B[i]=false có nghĩa i là phần tử không thuộc tệp 2. Thuật toán: + Khởi động mọi giá trị của A[] và B[] là False + Đọc từng phần tử của tệp 1, giả sử số đọc đợc của dãy là X, ta đánh dấu phần tử A[X]=true {Xác nhận số X thuộc tệp 1}. Thực hiện đọc và đánh dấu cho đến khi đọc hết tệp 1. Khi đó ta thu đợc một mảng A[] trong đó A[i]=true tại các chỉ số i mà ít nhất i xuất hiện một lần trong tệp 1. + Đọc từng phần tử của tệp 2, giả sử số đọc đợc của dãy là Y, ta đánh dấu phần tử B[Y]=true {Xác nhận số Y thuộc tệp 2}. Thực hiện đọc và đánh dấu cho đến khi đọc hết tệp 2. Khi đó ta thu đợc một mảng B[] trong đó B[i]=true tại các chỉ số i mà ít nhất i xuất hiện một lần trong tệp 2. + Duyệt từ đầu mảng đến cuối mảng A[] B[], nếu tại vị trí nào mà A[i] và B[i] có giá trị True thì ta xuất chỉ số đó ra. Kết quả ta đợc một tập các phần tử cần tìm. Chơng trình mẫu: const f1='tep1.inp'; f2='tep2.inp'; f3='tep3.out'; type mmc=array[1 32767] of boolean; var n,i,j,a:longint; k:mmc; f,fi:text; procedure doctep; begin assign(f,f1); reset(f); readln(f,n); for i:=1 to n do begin read(f,a); k[a]:=true; end; close(f); end; procedure xulivaxuat; begin CTT Media Phơng pháp đánh dấu phần tử đợc chọn assign(fi,f3); rewrite(fi); assign(f,f2); reset(f); readln(f,n); for i:=1 to n do begin read(f,a); if k[a]=true then begin write(fi,' ',a); k[a]:=false; end; end; close(f); close(fi); end; BEGIN doctep; xulivaxuat; end. Nhận xét: Chơng trình này chạy nhanh gấp 400 lần so với chơng trình đã viết theo thuật toán đơn giản trên. CTT Media . dữ liệu Lọc dữ liệu là một vấn đề có ý nghĩa to lớn trong xử lý thông tin. ý nghĩa thực tiễn của lọc dữ liệu là nhằm loại bỏ các dữ liệu d thừa, không. là phần tử không đợc chọn. 2- ứng dụng PP đánh dấu trong bài toán sắp xếp dãy số Sắp xếp dữ liệu đóng vai trò rất quan trọng trong xữ lý thông tin. ý nghĩa

Ngày đăng: 01/08/2013, 05:41

TỪ KHÓA LIÊN QUAN

w