Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 17 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
17
Dung lượng
300,11 KB
Nội dung
MỤC LỤC I MỞ ĐẦU Lý chọn đề tài Mục đích nghiên cứu Phạm vi đề tài Phương pháp nghiên cứu II NỘI DUNG Cơ sở lý luận a.Thuật tốn tìm kiếm nhị phân b Cài đặt c Đánh giá độ phức tạp thời gian thuật toán Các biến thể thuật tốn tìm kiếm nhị phân (Thuật tốn tìm phần tử có giá trị gần X) a Dãy tăng – Tìm phần tử lớn nhỏ x (chỉ số lớn nhất) b Dãy tăng – Tìm số bé lớn x (chỉ số bé nhất) c Dãy tăng –Tìm số bé lớn x (chỉ số lớn nhất) e Dãy giảm – Tìm phẩn tử nhỏ x d Dãy giảm – Tìm phần tử cuối lớn x Bài tập áp dụng a Bài toán 1: Bước nhảy xa (Đề thi lớp 11 trại hè Hùng vương năm 2014) b Bài toán 2: (Đề thi giáo viên giỏi cấp tỉnh Thanh Hóa năm học 2013-2014) c Bài tốn 3: CAKES d Bài tốn 4: BÍ HIỂM III KẾT LUẬN VÀ ĐỀ XUẤT Tài liệu tham khảo Trang 1 2 3 5 6 7 8 10 12 16 I MỞ ĐẦU Lý chọn đề tài Thuật toán tư thuật toán nội dung quan trọng hình thành văn hóa tin học phổ thơng xun suốt tồn cấp trung học phổ thơng Đây vấn đề khó đưa vào từ lớp 10 để học sinh có điều kiện tiếp thu nhanh kiến thức lớp 11 Tuy nhiên bồi dưỡng học sinh giỏi thuật toán vấn đề trọng tâm cốt lõi Học sinh cần phải hiểu kỹ thuật toán học thuật toán điển hình Trong chương trình sách giáo khoa Tin học lớp 10 lựa chọn tốn điển hình dạng đơn giản xếp tìm kiếm Các thuật tốn giải tốn trình bày kỹ lưỡng từ đơn giản đến phức tạp Trong thuật tốn tìm kiếm nhị phân đánh giá khó học sinh trung học phổ thơng nói chung Vì thuật tốn giảm tải chương trình học đại trà Tuy nhiên bồi dưỡng học sinh giỏi môn tin cấp thuật tốn tìm kiếm nhị phân lại đặc biệt quan trọng Thuật tốn tìm kiếm nhị phân dùng để tìm kiếm phần tử danh sách xếp, ví dụ danh bạ điện thoại xếp theo tên, tìm kiếm số điện thoại người theo tên người Đây thuật toán quan trọng Tin học, áp dụng nhiều giải tốn, làm giảm nhiều thời gian tìm kiếm, giúp chương trình chạy nhanh Với lí tơi chọn đề tài ‘‘Thuật tốn tìm kiếm nhị phân bồi dưỡng học sinh giỏi mơn Tin học“ Mục đích nghiên cứu Trong phạm vi đề tài tơi muốn nghiên cứu biến thể thuật tốn tìm kiếm nhị phân số tập áp dụng thuật tốn tìm kiếm nhị phân biến thể Thơng qua cung cấp thêm phương pháp tư duy, tiếp cận để giải toán bồi dưỡng HSG cấp tỉnh, giúp học sinh hình thành kỹ giải toán tin học rèn luyện tư thuật tốn, từ rèn luyện tư lập trình Cũng qua đề tài, tơi muốn đồng nghiệp trao đổi, trau dồi chun mơn nhằm góp phần nâng cao trình độ chun mơn nghiệp vụ khả mở rộng kiến thức Với thân nghiên cứu đề tài sáng kiến kinh nghiệm hội tốt để nghiên cứu khoa học làm quen với phương pháp làm khoa học phạm vi hẹp hy vọng với nổ lực thân giúp đỡ đồng nghiệp có đề tài khoa học tốt, lý thú hiệu Phạm vi đề tài Đề tài áp dụng học sinh giỏi với nhiệm vụ chủ yếu ôn thi học sinh giỏi bồi dưỡng kiến thức cho học sinh yêu thích mơn tin Phương pháp nghiên cứu Để hồn thành đề tài này, tiến hành áp dụng số phương pháp nghiên cứu sau: Phương pháp đặt vấn đề - giải vấn đề, Phương pháp phân tích tổng hợp, Phương pháp so sánh đối chiếu, Phương pháp thực nghiệm II NỘI DUNG Cơ sở lý luận a.Thuật tốn tìm kiếm nhị phân Bài toán: Cho dãy A gồm N phần tử nguyên từ A1, A2, An xếp thành dãy không giảm số nguyên Yêu cầu: Tìm kiếm nhị phân giải thuật tìm kiếm nhanh Giải thuật làm việc dựa nguyên tắc chia để trị (Divide and Conquer) Để giải thuật làm việc cách xác tập liệu nên dạng xếp Tư tưởng thuật tốn: Tìm kiếm nhị phân tìm kiếm phần tử cụ thể cách so sánh phần tử vị trí tập liệu Nếu tìm thấy kết nối mục phần tử trả Nếu phần tử cần tìm lớn giá trị phần tử phần tử cần tìm tìm mảng nằm bên phải phần tử giữa; khơng tìm mảng nằm bên trái phần tử Tiến trình tiếp tục mảng tìm hết phần tử mảng Giả sử cần tìm vị trí giá trị 31 mảng bao gồm giá trị hình sử dụng Binary Search: Đầu tiên, chia mảng thành hai nửa theo phép toán sau: chỉ-mục-giữa=ban-đầu + (cuối+ban-đầu)/2 Với ví dụ + (9 – 0)/ = (giá trị 4.5) Do mục mảng Bây so sánh giá trị phần tử với phần tử cần tìm Giá trị phần tử 27 phần tử cần tìm 31, khơng kết nối Bởi giá trị cần tìm lớn nên phần tử cần tìm nằm mảng bên phải phần tử Chúng ta thay đổi giá trị ban-đầu thành chỉ-mục-giữa + lại tiếp tục tìm kiếm giá trị chỉ-mục-giữa ban-đầu = chỉ-mục-giữa + chỉ-mục-giữa=ban-đầu + (cuối+ban-đầu)/2 Bây mục Chúng ta so sánh giá trị mục với giá trị cần tìm Giá trị mục khơng kết nối, ngồi giá trị cần tìm nhỏ giá trị mục cần tìm mảng bên trái mục Tiếp tục tìm chỉ-mục-giữa lần Lần có giá trị So sánh giá trị mục với giá trị cần tìm thấy kết nối Do kết luận giá trị cần tìm 31 lưu giữ vị trí mục Tìm kiếm nhị phân chia đơi lượng phần tử cần tìm giảm số lượng phép so sánh cần thực nên giải thuật tìm kiếm thực nhanh b Cài đặt Function Tknpcb(X:longint):longint; Var d, c, g: Longint; Begin d:=1; c:=N; While d=2 T(1) = Với phương pháp truy hồi, viết T(n)=1+1+T(n/22) =1+1+1+T(n/23) Như T(n) có dạng T(n)=k+T(n/2k) Cuối ta chứng minh T(n)=[log2n]+1 hay T(n)=O(log2n) Rõ ràng so với thuật tốn tìm kiếm tuần tự, chi phí tìm kiếm nhị phân nhiều Đây phương pháp tìm kiếm dựa giá trị so sánh đánh giá tốt Tuy nhiên dãy khóa ln biến động (được bổ sung thêm loại bớt đi) lúc chi phí cho xếp lại lên rõ điều bộc lộ nhược điểm phương pháp tìm kiếm nhị phân Các biến thể thuật tốn tìm kiếm nhị phân (Thuật tốn tìm phần tử có giá trị gần X) Trên thực tế không lúc người ta yêu cầu tìm kiếm phần tử X mà u cầu tìm phần tử gần X Vì với khác với u cầu tìm kiếm khác dễ dàng sửa đổi cho phù hợp sử dụng cách tìm kiếm nhị phân vừa trình bày a Dãy tăng – Tìm phần tử lớn nhỏ x (chỉ số lớn nhất) function tim2(r,x : longint) : longint; var d,c,g : longint; begin d:=0;c:=r; g:=(d+c) div 2; while (gd) and (gc) begin if b[g]>=x then c:=g else d:=g; g:=(d+c) div 2; end; for g:=c downto d if b[g]=x then c := g; else d:= g; end; g := (d + c) / 2; for g := d to c if a[g]>=x then exit(g); c Dãy tăng –Tìm số bé lớn x (chỉ số lớn nhất) sort(a); function tim2(r,x : longint) : longint; var d,c,g : longint; d:=1, c:=r; g:= (d + c) / 2; while (d=g) and (g=c) begin if a[g]>x then c := g; else d:= g; g:= (d + c) / 2; end; for g := c to d if a[g]x then d:=g else c:=g; g:=(d+c) div 2; end; for g:=c downto d if b[g]>x then exit(g); end; e Dãy giảm – Tìm phẩn tử nhỏ x function tim1(r,x : longint) : longint; var d,c,g : longint; begin d:=0;c:=r; g:=(d+c) div 2; while (gd) and (gc) begin if b[g]>x then d:=g else c:=g; g:=(d+c) div 2; end; for g:=d to c if b[g]>x then exit(g); end; Bài tập áp dụng a Bài toán 1: Bước nhảy xa (Đề thi lớp 11 trại hè Hùng vương năm 2014) Cho dãy A gồm N phần tử nguyên không âm A 1, A2, An Một bước nhảy từ phần tử Ai đến phần tử Aj gọi bước nhảy xa dãy thỏa mãn điều kiện sau: + ≤i < j ≤ N +Aj–Ai≥P + j –i lớn (Khi j –i gọi độ dài bước nhảy xa dãy Yêu cầu: Tìm độ dài bước nhảy xa dãy A Dữ liệu vào: Từ tệp JUMP.INP cps cấu trúc sau: Dòng 1: Gồm hai số nguyên N P (1≤ N≤105 ; 0≤ P≤109) Dòng 2: Gồm N số nguyên A1, A2, An (0≤ Ai≤109 với 1≤ i≤N) Kết ghi vào têp JUMP.OUT gồm số nguyên dương độ dài bước nhảy xa dãy (Nếu bước nhảy thỏa mãn ghi kết 0) JUMP.IN JUMP.OUT 3 Giải thuật: - Gọi T[i] phần tử nhỏ từ A1 đến Ai Vậy T dãy giảm dần - Duyệt tất số từ j đến N Với số j ta tìm kiếm nhị phân đoạn số [1,j-1] dãy T phần tử lớn thỏa mãn ≤A[j] –p b Bài toán 2: (Đề thi giáo viên giỏi cấp tỉnh Thanh Hóa năm học 2013-2014) Xét dãy số nguyên dương khác đôi a1, a2, an Với số nguyên x cho trước Hãy định số cặp (ai, aj) thỏa mãn điều kiện: + ai+aj=x + 1≤i, j≤n Dữ liệu vào: File văn BAI3.INP: + Dòng chứa số nguyên dương n + Dòng thứ chứa n số nguyên a1, a2, an, số cách dấu cách trống + Dòng thứ chứa số nguyên x Kết ra: File văn BAI3.OUT chứa số nguyên cặp số tìm Giới hạn: 1≤ ai≤109 ; 1≤ i≤ n ≤105;1≤x≤2.109 Ví dụ: BAI3.IN BAI3.OUT 12 10 11 13 Thuật toán - Đầu tiên ta lại dãy số theo thứ tự tăng dần - Bước ta xét số hạng từ a đến an-1, xét đến số hạng ta tìm số j1 nhỏ thỏa mãn j1 > i + aj1 = x đoạn từ i +1 đến n dãy tìm kiếm nhị phân, ta tìm tiếp số j2 nhỏ thỏa mãn j2 > i + aj2 = x đoạn từ j1 đến n dãy tìm kiếm nhị phân (đây toán bản), tất nhiên j1 khơng tồn khơng tìm j2 Nếu khơng tồn j1 j2 xét sang số hạng tiếp theo, ngược lại ta cộng thêm vào tổng s lượng j2- j1 +1 c Bài toán 3: CAKES Nghệ nhân nấu ăn Tư Mập sử dụng hệ thống gồm n bếp điện để thực nấu ăn khiến ơng vinh danh, “gatơ hải sản” Thời gian để thực nấu suất ăn bếp điện tương ứng t 1, t2, …, tn giây Yêu cầu: Cho biết s số lượng thực khách cần phục vụ, xác định thời gian tối thiểu cần thiết để Nghệ nhân Tư Mập nấu xong s suất ăn hệ thống bếp điện khách sạn Để nấu suất ăn sử dụng bếp Dữ liệu: Vào từ file văn CAKES.INP: - Dòng chứa số lượng suất ăn s (0 < s < 10 15) số lượng bếp điện n (0 < n < 20) - Dòng thứ hai chứa n số nguyên dương t1, t2, …, tn, số nhỏ 500 Kết quả: Ghi file văn CAKES.OUT số ngun thời gian tối thiểu tìm tính giây Ví dụ: CAKES.INP CAKES.OUT 32 50 70 100 Thuật toán Ta chặt nhị phân thời gian tối thiểu phải tìm theo đề (trong chương trình ta dùng biến kq để biểu diễn giá trị này) Ban đầu phạm vi tìm kiếm thuộc đoạn [L =1, R = s * 500] (thời gian tối thiểu để nấu xong s suất ăn nhỏ lớn s * 500 thời gian nấu suất ăn = s OK(t) :=true, ngược lại OK(T) := false 10 Chương trình const fi='cakes.inp'; fo='cakes.out'; var f:text; s,n,kq:longint; a:array[1 21] of longint; procedure doc; var i:longint; begin assign(f,fi); reset(f); readln(f,s,n); for i:=1 to n read(f,a[i]); close(F); end; function ok(d:longint):boolean; var sl,i:longint; begin sl:=0; for i:=1 to n sl:=sl+(d div a[i]); if sl>=s then exit(true) else exit(false); end; procedure xuli; var l,r,gi:longint; begin l:=1;r:=s*500; while l s +1 OK := false ( nghĩa với u đồng tiền khơng thỏa đề khơng thể mua mặt hàng có gia s +1 i-1 đồng tiền đầu khơng mua mặt hàng này, đồng tiền từ đồng thứ i đến đồng thứ u có mệnh giá lớn s + nên khơng giúp hơn) khơng xét đồng tiền thứ i +1 đến đồng thứ u Nếu = k OK := true ngược lại OK := false; 13 Chương trình Const fi='riddle.inp'; fo='riddle.out'; nmax=100010; var f,f1:text; a,a1:array[1 nmax] of longint; n,k:longint; s:int64; function ok(u:longint):boolean; var i:longint; begin s:=0; for i:=1 to u if a1[i]=k then exit(true); exit(false); end; procedure quicksort(l,r:longint); var i,j,c,gi:longint; begin i:=l;j:=r; gi:=a1[l+random(r-l+1)]; repeat while a1[i]gi dec(j); if ij; if l