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

SK dem don gian bang thuat toan lua bo vao chuong

23 24 0

Đ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

Trong kỹ thuật lập trình, các bài toán có liên quan đến đếm các đối tượng rất gần gũi và dễ giải đối với chúng ta vì tính dễ xây dựng thuật toán cho nó. Tuy nhiên, những bài toán ″đếm″ thường yêu cầu với dữ liệu rất lớn. Nếu không biết tổ chức dữ liệu và thuật toán hiệu quả thì khó có thể đưa ra lời giải. Để hệ thống lại các chuyên đề bồi dưỡng HSG chuyên Tin học mà tôi đã dạy trong nhiều năm qua, đồng thời qua quá trình nghiên cứu, giảng dạy, tham khảo ý kiến với đồng nghiệp,..., tôi thấy rằng một số bài toán Tin học có liên quan đến việc đếm. Chính vì vậy, một trong những cách tiếp cận để xử lý hiện tượng này là “ĐẾM ĐƠN GIẢN BẰNG THUẬT TOÁN LÙA BÒ VÀO CHUỒNG”.

Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG ĐẶT VẤN ĐỀ: 1.1 Lý chon đề tài: Trong thời đại khoa học công nghệ ngày nay, nhân lực có trình độ cao khơng tiền đề mà cịn yếu tố có tính định cho phát triển đất nước Để tạo nguồn nhân lực có trình độ cao vấn đề phát hiện, bồi dưỡng sử dụng người tài có vai trị quan trọng Nhận thức vai trò quan trọng nhân tài, Đảng Nhà nước ta có chủ trương, sách để phát bồi dưỡng nhân tài Để góp phần thực chủ trương đó, ngành Giáo dục cần trọng nâng cao chất lượng bồi dưỡng học sinh giỏi từ bậc học sở, nhà quản lý phải đề biện pháp quản lý dạy học bồi dưỡng học sinh giỏi để công tác đạt kết cao Chính vậy, nhiệm vụ trị quan trọng người giáo viên nghiên cứu, tìm tịi, đúc kết kiến thức, biện pháp cách khoa học để bồi dưỡng học sinh giỏi đạt kết cao 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, toán ″đếm″ thường yêu cầu với liệu lớn Nếu tổ chức liệu thuật tốn hiệu khó đưa lời giải Để hệ thống lại chuyên đề bồi dưỡng HSG chuyên Tin học mà dạy nhiều năm qua, đồng thời qua trình nghiên cứu, giảng dạy, tham khảo ý kiến với đồng nghiệp, , tơi thấy số tốn Tin học có liên quan đến việc đếm Chính vậy, cách tiếp cận để xử lý tượng “ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG” 1.2 Xác định mục đích nghiên cứu: Đếm công việc quan trọng đơn giản mà làm thường ngày, điều khơng cần phải bàn đến làm gì? Điều đáng nói cơng việc có vẽ nhàm chán lại chứa bao điều thú vị, gặp toán yêu cầu ta phải đếm Đếm đơn đếm 1, 2, 3, mà cần người đếm khéo léo tổ chức liệu có chút kỹ thuật Bên cạnh giúp em học sinh có kiến thức tốt, tư tốt lập trình Các phương pháp đếm đơn giản vấn đề mà người lập trình tin học cần phải nắm vững 1.3 Đối tương nghiên cứu Trong nghiên cứu này, tơi tập trung vào tìm hiểu giải số toán Tin học liên quan đến việc đưa giá trị giống vào "chuồng", sau duyệt lại "chuồng" tìm hay đếm "chuồng" có giá trị thỏa mãn u cầu tốn Hay nói cách khác giải số yêu cầu toán Tin học thuật tốn "Lùa bị vào chuồng" 1.4 Đối tượng khảo sát, thực nghiệm: Đối tượng khảo sát, thực nghiệm em học sinh chọn bồi dưỡng để dự thi học sinh giỏi Tin cấp huyện, em học sinh giỏi Tin lớp huyện chọn bồi dưỡng dự thi học sinh giỏi cấp tỉnh, bồi dưỡng giáo viên dự thi giáo viên dạy giỏi cấp huyện, cấp tỉnh GV: Nguyễn Trương Tiên Năm học: 2016-2017 Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG 1.5 Các phương pháp nghiên cứu Phương pháp suy luận, tổng hợp: kết hợp từ nhiều nguồn tài liệu tham khảo tác giả tra cứu mạng internet với tập, đề thi Học sinh Giỏi cấp rút kinh nghiệm, hệ thống lại kiến thức, mở hướng Phương pháp trò chuyện - vấn: trao đổi tâm tình với nhiều học sinh giỏi để nắm tình hình việc giải tốn tin Phương pháp khảo sát: thân tham gia giảng dạy lớp, đội tuyển HSG, kỳ tập huấn, đề; tham khảo đồng nghiệp, quý Thầy Cô giảng dạy đội tuyển nhiều năm nên có nắm tình hình sử dụng phương pháp làm em học sinh Phương pháp phân tích lý luận: phân tích giúp học sinh nắm thật rõ chất vấn đề, lựa chọn phương pháp giải cho phù hợp 1.6 Phạm vi thời gian nghiên cứu: Trong đề tài này, nghiên cứu phạm vi nhỏ sử dụng thuật tốn "Lùa bị vào chuồng" để "đếm" số Toán Tin liên quan Để hồn thành đề tài này, tơi tiến hành sưu tầm, tìm hiểu, nghiên cứu kể từ đầu năm học 2014-2015 NỒI DUNG: 2.1 Cơ sở lý luân đề tài Trong năm liên tiếp dạy bồi dưỡng HSG môn Tin Học lớp 8, đội tuyển thi HSG cấp Huyện, tham khảo ý kiến đồng nghiệp chuyên dạy bồi dưỡng đội tuyển Huyện, trường THCS, THPT, rút điều “CÔNG VIỆC ĐẾM RẤT QUAN TRỌNG TRONG DẠY LẬP TRÌNH” Được động viên khuyến khích q Thầy/Cơ tổ giáo viên tham gia bồi dưỡng, mạnh dạng chọn viết đề tài “ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG” Đề tài có kết hợp giảng tài liệu tham khảo để phân tích, tổng hợp, hệ thống 2.2 Thưc trang vấn đề nghiên cứu Đa số học sinh, giáo viên tham gia bồi dưỡng môn Tin học ngại, sợ giải tốn Tin học có liên quan đến việc đếm; lúng túng q trình phân tích, tổ chức liệu, tìm thuật tốn hiệu để tìm chất vận dụng kiến thức cách thích hợp Trước hết thực đổi phương pháp giảng dạy Tin học làm cho học sinh tìm kết sáng tạo, lời giải hay số “dạng tốn tin có liên quan đến việc đếm”; giúp thân nắm vững tư thuật tốn, khả lập trình, đồng thời trao đổi học tập kinh nghiệm Quý Thầy Cô môn Tin học huyện số huyện tỉnh 2.3 Mơ tả, phân tích giải pháp: 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, toán GV: Nguyễn Trương Tiên Năm học: 2016-2017 Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TOÁN LÙA BÒ VÀO CHUỒNG “đếm” thường yêu cầu với liệu lớn Nếu tổ chức liệu thuật tốn hiệu khó đưa lời giải tốt Một cách tiếp cận để xử lý tượng sử dụng thuật toán “lùa bị vào chuồng” Tư tưởng thuật tố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 tố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 Bài 1: Đếm bị Tên chương trình: Dembo.pas Bài tốn đặt giả sử cánh đồng rộng thả nhiều bị (N con), bị đeo thẻ có số hiệu nguyên dương (là số tháng tuổi nó) Tất nhiên, hai bị tháng tuổi đeo thẻ có số hiệu Làm để đếm loại bị có nhiều nhất? Bài tốn phát biểu lại sau: Nhập từ bàn phím số nguyên dương N (0 < N ≤ 200) phần tử mảng chiều A(N) có giá trị nguyên dương (0 < A[i] ≤ 100) Giá trị xuất nhiều A xuất lần? Ví dụ: A(12) = {2,3,2,4,5,6,2,6,7,1,6,2} A(12) có số phần tử giá trị nhiều Số lượng phần tử xuất lần a/ Cách 1: Chưa vận dụng thuật toán “Lùa bò vào chuồng”: * Ý tưởng: Dùng hai vòng lặp i (1≤i≤N) j (1≤j≤N) lồng Với giá trị A[i], ta đếm số lần xuất tương ứng A[j] So sánh số lần xuất hai giá trị A[i] A[i+1], ta lấy giá trị xuất nhiều Thuật toán: +Input: Số nguyên dương N dãy N số nguyên dương A +Output: Giá trị xuất nhiều ứng với số lần xuất dãy A -Bước 1: Nhập N dãy số nguyên A -Bước 2: Max←0;i←0; -Bước 3: i←i+1; Nếu i>N chuyển Bước -Bươc 4: dem←1;j←0; -Bước 5: j←j+1; Nếu j>N chuyển đến Bước -Bước 6: Nếu ij A[i]=A[j] dem←dem+1; Quay lại Bước -Bước 7: Nếu dem>Max Max←dem gt←A[i]; Quay lại Bước GV: Nguyễn Trương Tiên Năm học: 2016-2017 Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG -Bước 8: Thông báo giá trị Max gt; Kết thúc thuật tốn * Chương trình mẫu: uses crt; var A:array[1 50]of word; n:word; procedure nhap; var i:word; begin clrscr; write('Cho biet so luong bo='); readln(n); writeln('Nhap tuoi cho moi bo:'); for i:=1 to n begin write('A[',i,']='); readln(A[i]); end; end; procedure xuly; var i,j,max,dem,gt:word; begin max:=0; for i:=1 to n begin dem:=1; for j:=1 to n if (ij) and (a[i]=a[j]) then inc(dem); if dem>max then begin max:=dem; gt:=A[i]; end; end; Write('So ’,gt,’ co so luong lon nhat la ',Max); end; begin nhap; xuly; readln; end b/Cách 2: Vận dụng thuật tốn “Lùa bị vào chuồng” Để giải toán người ta dùng thuật tốn “lùa bị vào chuồng” gồm bước: Bước 1: Đóng dãy chuồng bị đánh số chuồng số tự nhiên liên tiếp từ đến max (max số tháng tuổi bò già nhất), ban đầu chuồng chưa có bị GV: Nguyễn Trương Tiên Năm học: 2016-2017 Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG Bước 2: Lùa bị vào chuồng có số hiệu số thẻ Bước 3: Duyệt dãy chuồng bị tìm chuồng có nhiều bị Áp dụng thuật tốn vào tập: Bước 1: Giả sử bò thứ i có tháng tuổi a[i] (1 ≤ i ≤ n) Coi mảng b(n) dãy chuồng bò, b[x] số lượng bị (có x tháng tuổi) chuồng có số hiệu x, ban đầu phần tử mảng b(n) Bước 2: Con bị có tháng tuổi a[i] phải vào chuồng bị có số hiệu a[i] Thêm bò vào chuồng a[i] tương ứng với lệnh inc(b[a[i]]) Bước 3: Duyệt mảng b, tìm số phần tử lớn * Lưu ý: Do đề cho < A[i] ≤ 100, nhiên, thường liệu để kiểm tra không đến số 100 Nên để việc duyệt mảng B tối ưu, ta cần biến để lưu giữ giá trị lớn mảng A Chương trình tham khảo Uses crt; Const max = 200; Var N: integer; A: array[1 max] of byte; B: array[1 max] of byte; maxs1, maxA, i, li:integer; BEGIN Clrscr; Write('Nhap so nguyen duong N = ’);Readln(N); MaxA:=0; For i := to N Begin Write('A[',i:2,'] = ’);Readln(A[i]); if A[i]>MaxA then MaxA:=A[i]; End; Fillchar (B, sizeof (B) ,0) ; {Tao day chuong bo rong chua co bo} For i := to N inc (B [A[i] ] ) ; {Tang them bo vao chuong co so hieu A[i]} maxsl := 0; li:=0; For i := to MaxA {Duyet day chuong tim chuong co nhieu bo nhat} if B[i] > maxsl then Begin maxsl := B[i]; li := i; End; Write('So ’,li,’ co so luong lon nhat la ',B[li]); Readln; END * Giữa hai cách giải trên, rõ ràng cách giải thuật tốn "Lùa bị vào chuồng" có độ phức tạp nhỏ nhiều, thuật tốn ngắn gọn, thời gian xử lý ngắn đơn vòng lặp, cách giải thứ phải sử dụng hai vòng lặp lồng (duyệt theo chiều sâu) với giá trị phải xuất phát từ đầu * Do đề yêu cầu tìm số xuất nhiều giá trị tương ứng nên cách 2, ta gặp vấn đề lãng phí nhớ (mảng B) Do đó, để tối ưu nhớ, ta "lùa tất bò tuổi vào chuồng " mảng A Dĩ nhiên, ban đầu chuồng chưa có GV: Nguyễn Trương Tiên Năm học: 2016-2017 Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG bị nên tất phần tử dãy A có giá trị Chương trình tham khảo Uses crt; Const max = 200; Var N: integer; A: array[1 max] of byte; maxs1, maxA, x, i, li:integer; BEGIN Clrscr; fillchar(A,sizeof(A),0) Write('Nhap so nguyen duong N = ’);Readln(N); MaxA:=0; For i := to N Begin Write('A[',i:2,'] = ’);Readln(x); inc(A[x]); {Tang them bo vao chuong co so hieu x} if x>MaxA then MaxA:=x; End; maxsl := 0; li:=0; For i := to MaxA {Duyet day chuong tim chuong co nhieu bo nhat} if A[i] > maxsl then Begin maxsl := A[i]; li := i; End; Write('So ’,li,’ co so luong lon nhat la ',A[li]); Readln; END * Thơng qua chương trình tham khảo này, rõ ràng ta thấy "thuật tốn: lùa bị vào chuồng" tối ưu nhớ, chương trình ngắn gọn, độ phức tạp thuật toán cải thiện nhiều (chỉ phụ thuộc vào giá trị biến N) * Dùng thuật toán “Lùa bị vào chuồng” để giải tốn sau, thơng qua thấy rằng: Nếu khơng có thuật tốn vệc giải tốn sau phức tạp Bài 2: Dự tiệc Tên chương trình: Dutiec.pas Ơng An đến dự buổi tiệc Buổi tiệc có N người (0 < N < 500.000) Mỗi người dự tiệc cài lên áo bơng hoa có ghi số nguyên dương X (X < 106) cho biết người khách dự tiệc phịng có số X Hầu hết phịng có số lượng khách số chẵn, có phịng có số lượng khách số lẻ Để đảm bảo đủ cặp cho việc khiêu vũ nên ban tổ chức cần tìm số hiệu phịng khách có số lượng khách số lẻ để ghi số cho ông An Yêu cầu: Cho trước danh sách khách dự tiệc với số áo họ, giúp ban tổ chức tìm số hiệu phịng khách có số lượng khách số lẻ Dữ liệu vào: Cho file văn DUTIEC.INP, gồm: ■ Dòng ghi số N cho biết số khách buổi tiệc ông An đến ■ Trong N dòng tiếp theo, dòng ghi số nguyên dương cho biết số ghi áo người khách thứ i Dữ liệu ra: Ghi file văn DUTIEC.OUT gồm số nguyên dương Đó số hiệu phịng có số lượng khách số lẻ GV: Nguyễn Trương Tiên Năm học: 2016-2017 Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG Ví dụ: DUTIEC.INP 2 DUTIEC.OUT Yêu cầu toán hiểu đơn giản tìm giá trị phần tử xuất lần Ta giải tốn theo cách Bài Tuy nhiên, độ phức tạp thuật toán lớn nhiều Để giải tốn này, ta nên dùng thuật tốn “lùa bị vào chuồng” gồm bước sau: Bước 1: Đóng dãy phòng đánh số phòng số tự nhiên liên tiếp từ đến max (max số hiệu lớn khách tham gia dự tiệc), ban đầu phịng chưa có người khách Bước 2: Đưa tất người khách vào phòng ứng với số hiệu ghi áo Bước 3: Duyệt tất phịng tìm phịng có tổng số người khách phịng số lẽ phịng phịng cần tìm * Lưu ý: Đề cho số hiệu ghi áo người khách N chuyển đến bước +B4: Nhập giá trị x thứ i; A[x]←A[x]+1; +B5: Nếu Max < x Max←x; Quay lại bước +B6: i←0; So←0; +B7: i←i+1; Nếu i>Max chuyển đến bước +B8: Nếu A[i] mod 0 So←i; Quay lại bước +B9: In So tìm kết thúc thuật toán uses crt; var A:array[1 250]of byte; N,max:longint; f:text; GV: Nguyễn Trương Tiên Chương trình tham khảo procedure xuly; var i:longint; begin Năm học: 2016-2017 Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TOÁN LÙA BÒ VÀO CHUỒNG procedure kt_docdl; assign(f,'dutiec.out'); var i,x:longint; rewrite(f); begin for i:=1 to max assign(f,'dutiec.inp'); if a[i] mod 20 then {$I-} reset(f);{$I+} begin if IOResult>0 then write(f,i); begin break; rewrite(f);reset(f); end; end; close(f); fillchar(A,sizeof(A),0); end; readln(f,n);max:=0; begin for i:=1 to n kt_docdl; begin xuly; readln(f,x); inc(A[x]); end if x>max then max:=x; end; close(f); end; Bài 3: Chuổi kiểm tra Tên chương trình: ChuoiKT.pas Cho file văn có n dịng (3 < n < 30000), dịng chuỗi S có tối đa 255 kí tự, kí tự S[i] thuộc [‘a’ ’z’,'0' '9'] với < i < length(S) Trong đó, có chuỗi S có số lần xuất số lẻ, chuỗi khác có số lần xuất số chẵn u cầu: Tìm chuỗi S (có số lần xuất lẻ) Dữ liệu vào: từ file ‘CHUOIKT.inp’ ■ Dòng đầu số nguyên n ■ Dòng thứ i + n dòng sau, dòng chuỗi kí tự (1 < i < n) Kết quả: ghi vào file ‘CHUOIKT.out’ chứa chuỗi kí tự tìm theo yêu cầu Ví dụ: CHUOIKT.INP CHUOIKT.OUT lop tin abcdef bbcc lop tin abcdef bbcc abcdef abcdef Bài toán tương tư toán số (Dự tiệc) điểm khác biệt phần tử có giá trị chuỗi ký tự nên ta tổ chức kiểu liệu Ở toán này, ta dùng mảng S để lưu tất phần tử chuỗi theo đề, dùng mảng A để đánh dấu vị trí chuỗi tương ứng có S xuất số chẵn ứng với giá trị True (Các phần tử xuất với số lần chẵn lùa vào chuồng), ban đầu mảng A có giá trị False Sau duyệt lại tồn mảng A, vi trí có giá trị False phần từ vị trí S phần tử cần tìm Thuật tốn minh họa thơng qua bước sau: GV: Nguyễn Trương Tiên Năm học: 2016-2017 Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG - Input: N, mảng S lưu N chuỗi phần tử , mảng A có N phần tử có giá trị False -Output: Phần tử S xuất số lẽ +B1: Nhập N, nhập mảng S, gán giá trị False cho toàn mảng A +B2: i←0; +B3: i←i+1 Nếu i>n chuyển tới bước 8; +B4: d←1;j←0; +B5: j←j+1 Nếu j>n chuyển tới bước 7; +B6: Nếu S[i]=S[j] ij d←d+1; Quay lại bước 5; +B7: Nếu d mod 2=0 a[i]←True; Quay lại bước 3; +B8: i←0; +B9: i←i+1; Nếu i>n chuyển tới bước 11; +B10: Nếu A[i]=False in chuỗi S[i] Ngược lại quay lại bước 9; +B11: Kết thúc thuật tốn Chương trình tham khảo uses crt; const f1='chuoikT.inp'; f2='chuoiKT.out'; max=100; var a:array[1 max]of boolean; s:array[1 max]of string; n:word;f:text; procedure khoitao_docdl; var i:word; begin assign(f,f1); {$I-};reset(f);{$I+} if IOResult>0 then begin rewrite(f);reset(f); end; readln(f,n); for i:=1 to n readln(f,s[i]); close(f); assign(f,f2);rewrite(f); end; procedure xuly(n:word); var i,j,d:word; begin fillchar(a,sizeof(a),false); {Mang a deu co gia tri False} for i:=1 to n begin d:=1; for j:=1 to n if (s[i]=s[j]) and (ij) then inc(d); if d mod 2=0 then a[i]:=true; {Neu dem tai co gia tri chan thi gan gia tri True cho a[i]} end; for i:=1 to n GV: Nguyễn Trương Tiên Năm học: 2016-2017 Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG if a[i]=false then begin writeln(f,s[i]); break; end; close(f); end; begin khoitao_docdl; xuly(n); end Bài 4: Số lần xuất ký tự Tên chương trình: kytu_xh.pas Viết chương trình nhập vào từ bán phím xâu kí tự S thơng báo hình số lần xuất chữ Tiếng Anh S (không phân biệt chữ hoa hay thường) Ví dụ: Nhập vào xâu "TIN HOC" Thơng báo hình: C:1 H:1 I :1 N:1 O:1 T:1 Ở toán này, ta sử dụng phương pháp duyệt theo chiều sâu độ phức tạp lớn khó thực việc thơng báo kết theo yêu cầu ký tự in theo trình tự theo alphabet Để đơn giản, ta việc khai báo mảng Dem ứng với ký tự phần tử Ban đầu mảng Dem ứng với phần tử ký tự Sau duyệt qua xâu S nhập, dồn phần tử loại có S vào mảng Dem (lùa vào chuồng) tăng số lượng tương ứng số dồn vào Điểm cần lưu ý xâu S có nhiều ký tự khác chữ Tiếng Anh nên trình "lùa vào chuồng", ta lùa chữ Chương trình tham khảo uses crt; var dem:array['A' 'Z'] of byte; s:string;ch,x:char;i:byte; begin clrscr; write('Chuoi s=');readln(s); fillchar(dem,sizeof(dem),0); for i:=1 to length(s) begin x:=upcase(s[i]); if (x>='A') and (x0 then writeln(ch,':',dem[ch]); readln; end Mở rộng cho tốn u cầu có phân biệt chữ hoa, chữ thường Bài 5: Tổng số khác Tên chương trình: tong_kn.pas (Đề thi giáo viên dạy giỏi cấp tỉnh khối THCS năm học 2016-2017) Cho mảng chiều A gồm N số tự nhiên (00 then writeln(f,t); begin close(f); rewrite(f);reset(f); end; end; begin fillchar(B,sizeof(B),0); kt_docdl; readln(f,n);max:=0; xuly; for i:=1 to n end begin read(f,x);B[x]:=B[x]+1; if x>max then max:=x; end; close(f); end; Bài 6: Tuyển nhân viên Tên chương trình: Recruit.pas Cơng ty phần mềm máy tính A có số lượng nhân viên lớn Để tiện việc quản lý, công ty cấp cho nhân viên mã số, mã số nhân viên số nguyên dương, hai nhân viên có mã số khác Tuy nhiên, sau thời gian số nhân viên nghỉ hưu chuyển công tác, nên công ty phải tiến hành tuyển thêm k nhân viên Các nhân viên sau tuyển vào cấp mã số, nhân viên mã số mã số phải số nguyên dương Yêu cầu: Với n nhân viên có (cịn lại) cơng ty tương ứng với mã số ai, a2, , an Hãy tìm k mã số nhỏ để cấp cho k nhân viên tuyển vào cho thỏa mãn hai nhân viên (cả nhân viên cũ nhân viên mới) có mã số khác Dữ liệu vào từ file ‘Recruit.inp’ có nội dung sau: ■ Dịng đầu hai số nguyên dương n k (k < n < 106) ■ n dòng tiếp theo, dòng thứ i số nguyên dương (i = 1, 2, , n; < 2*109) Kết ghi vào file ‘Recruit.out’ k mã số theo thứ tự từ nhỏ đến lớn (mỗi mã số dịng) Ví dụ: RECRUIT.INP RECRUIT.OUT 3 Hướng dẫn: ■ Cách 1: Thuật toán O(NlogN) dùng quicksort đủ chấp nhận ■ Cách 2: Dùng Distribution sort O(n + K) Trong toán này, dãy chuồng cần đóng GV: Nguyễn Trương Tiên 12 Năm học: 2016-2017 Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG số hiệu từ đến số hiệu 2*nmax (nmax = 106) chuồng chứa trạng thái có chưa có (true, false) Bằng cách chạy từ đến N, số có đánh dấu chuồng true Sau chạy từ đến N+k, số false in số file (chỉ in đủ k số) Chương trình tham khảo uses crt; procedure xuly; const f1='recreit.inp'; var i:word; f2='E:recreit.out'; begin ln=10000; assign(f,f2);rewrite(f); var N,K:word;f:text; i:=1; A:array[1 ln]of boolean; while (K>0) and (i0 then else inc(i); begin close(f); rewrite(f);reset(f); end; end; begin fillchar(A,sizeof(A),false); khoitao_docdl; readln(f,n,k);max:=0; xuly; for i:=1 to n end begin readln(f,x); A[x]:=true; end; close(f); end; Bài 7: Tần số Tên tệp chương trình:Freq.pas (Đề thi Olympic sinh viên 2001, khối đồng đội) Cho văn gồm không N (N≤50) 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) đoạn 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 FREQ.OUT 25 faculty of technology Hanoi National University aaAAAAAaaaaAAAAaAaAaAa cccCCCeeefffggg123456$#)(*+= GV: Nguyễn Trương Tiên 13 Năm học: 2016-2017 Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG Hướng dẫn: Bài toán tương tự số Chỉ khác in tần số lớn tìm đề cho tất ký tự (256 ký tự) không chữ tiếng Anh Do ta khơng nên dùng mảng ký tự để lưu số lượng tương ứng mà dùng mảng A có 256 phần tử dùng để lưu số lượng ký tự tương ứng Ban đầu, phần tử A Lần lược đọc hết dòng văn cho tệp, dòng, ta chuyển ký tự đọc thành số thứ tự tương ứng bảng mã ASCII ứng với giá trị k, sau tăng số lần xuất A[k] lần (A[k]←A[k]+1, tức lùa ký tự giống vào ơ) Sau duyệt lại mảng A từ 256 tìm phần tử có giá trị lớn giá trị cần tìm Lưu ý đề cho khơng phân biệt chữ hoa hay chữ thường nên gặp chữ hoa, ta cộng thêm cho 32 để trở thành chữ thường, tức K←K+32 Chương trình tham khảo uses crt; procedure output; var a:array[1 256] of longint; var f:text; i,m:longint; n:integer; begin procedure solve; assign(f,′FREQ.OUT′); var f:text;i,j,k:integer; Rewrite(f); s:string; ss:set of byte; m:=a[1]; begin for i:=2 to 256 fillchar(a,sizeof(a),0); if m < a[i] then m:=a[i]; ss:=[65 90]; {SS la cac ky tu hoa nhu A, B, } write(f,m); close(f); assign(f,′FREQ.INP′); end; {$I-}reset(f); {$I+} begin if IOResult>o then solve; begin output; rewrite(f);reset(f); end end; readln(f,n); for i:=1 to n begin readln(f,s); for j:=1 to length(s) begin k:=ord(s[j]); {Chuyen s[j] so tuong ung} if k in ss then k:=k+32; {chuyen chu thuong} inc(a[k]); end; end; close(f); end; Bài 8: Số nhỏ Tẻn tệp chương trình: Num_min.pas ( Đề thi chọn HSG tỉnh cấp THPT Hà Tĩnh) Nam người bạn Ngun tìm cách giải tốn liên quan tới số tự nhiên cần giúp đỡ Nguyên, thử thách lần dãy gồm N số tự nhiên nằm đoạn từ tới 10 9, tìm số tự nhiên nhỏ khơng có dãy số Vì số lượng só tự nhiên dãy số cho lê tới 10 phần tử nên việc tìm thủ cơng khơng thể mà cần thuật tốn để cài đặt vào máy tính nhờ máy tính tìm giúp u cầu: Cho dãy A gồm N (1≤N≤106) số tự nhiên Hãy tìm số tự nhiên nhỏ GV: Nguyễn Trương Tiên 14 Năm học: 2016-2017 Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG khơng xuất dãy A Ví dụ: Dữ liệu vào Kết N=5 Dãy số: N=9 Dãy số: Bài toán có nhiều cách giải, nhiên để tối ưu đơn giản hóa, ta áp dụng thuật tốn lùa bò vào chuồng sau: Dùng mảng Dem để đưa phần tử giá trị vào ô tương ứng, sau duyệt lại mảng Dem, kiểm tra xem phần tử Dem mà giá trị cần tìm nhỏ khơng có dãy số vị trí tương ứng Ban đầu phần tử Dem Vì gặp giá trị phần tử nào, ta "lùa vào chuồng" nên để tối ưu nhớ máy tính, ta không cần mảng để lưa dãy số cho Để giới hạn giá trị duyệt lại mảng Dem, trình nhập liệu đầu vào, ta cần xác định giá trị lớn có dãy số Lưu ý: Do đề yêu cầu số nguyên dương nên giới hạn bé mảng Dem từ số Thuật tốn minh họa thơng qua bước sau: -Input: Giá trị N N giá trị tương ứng , mảng Dem có giá trị ban đầu -Output: Số nhỏ dãy số cho +B1: Nhập N +B2: i←0; Max←0; +B3: i←i+1; Nếu i>N chuyển đến bước +B4: Nhập giá trị x thứ i; Dem[x]←Dem[x]+1; +B5: Nếu Max < x Max←x; Quay lại bước +B6: i←0; +B7: i←i+1; Nếu i>Max chuyển đến bước +B8: Nếu Dem[i] =0 i giá trị cần tìm; Ngược lại quay lại bước +B9: In giá trị i tìm kết thúc thuật tốn Chương trình tham khảo uses crt; procedure xuly; var Dem:array[0 1000]of longint; var i:longint; N,max:longint; f:text; begin procedure kt_docdl; assign(f,'Num_min.out'); var i,x:longint; rewrite(f); begin for i:=0 to max assign(f,'Num_min.inp'); if dem[i]=0 then {$I-} reset(f);{$I+} begin if IOResult>0 then writeln(f,i); GV: Nguyễn Trương Tiên 15 Năm học: 2016-2017 Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG begin break; rewrite(f);reset(f); end; end; close(f); fillchar(Dem,sizeof(Dem),0); end; readln(f,n);max:=0; begin for i:=1 to n kt_docdl; begin xuly; read(f,x);Dem[x]:=Dem[x]+1; End if x>max then max:=x; end; close(f); end; Bài 9: SỐ LƯỢNG NHĨM ĐỀ TÀI Tên tệp chương trình: Nhom_DT.pas ( Đề thi chọn HSG tỉnh cấp THPT Hà Tĩnh) Nhà trường phát động phong trào đăng ký làm sáng tạo khoa học kỹ thuật, tất ban lớp Nguyên tích cực than gia phân cơng vào nhóm đề tài Mỗi nhóm đề tài ký hiệu: , ví dụ Ngun phân cơng vào nhóm TIN gồm thành viên ký hiệu nhóm TIN Danh sách lập gồm ký hiệu nhóm tên thành viên, trình in ấn cột ký hiệu nhóm bị mờ khơng đọc cịn lại Ví dụ: Ký hiệu Thành viên TIN Việt TOAN Tuấn TIN Thái TIN Anh TOAN Chính Do lỗi in ấn Ký hiệu Thành viên TIN Việt TOAN Tuấn TIN Thái TIN Anh TOAN Chính Yêu cầu: Cho danh sách gồm N học sinh số thành viên nhóm tương ứng với học sinh Hãy xác định nhóm đề tài phân cơng Dữ liệu đảm bảo tốn có nghiệm Ví dụ: Dữ liệu vào N=5 3 N=10 5 5 2 Kết Mới nhìn, yêu cầu tốn khó giải quyết, nhiên, dựa vào ví dụ ta thấy giá trí có xuất nhiều lần hay lần ta đếm đề tài Vì thế, cách đơn giản để giải yêu cầu cảu áp dụng thuật toán "Lùa bị vào chuồng" hồn tồn tương tự Chỉ khác đếm "chuồng" có giá trị lớn số lượng đếm nhóm đề tài tìm Thuật tốn minh họa thông qua bước sau: GV: Nguyễn Trương Tiên 16 Năm học: 2016-2017 Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG -Input: Giá trị N N giá trị tương ứng, mảng Dem có giá trị ban đầu -Output: Số lượng nhóm đề tài tìm +B1: Nhập N +B2: i←0; Max←0; +B3: i←i+1; Nếu i>N chuyển đến bước +B4: Nhập giá trị x thứ i; Dem[x]←Dem[x]+1; +B5: Nếu Max < x Max←x; Quay lại bước +B6: i←0;d←0; +B7: i←i+1; Nếu i>Max chuyển đến bước +B8: Nếu Dem[i] >0 d ←d+1 quay lại bước +B9: In giá trị d tìm kết thúc thuật toán uses crt; var Dem:array[1 50]of byte; N,max:byte; f:text; procedure kt_docdl; var i,x:byte; begin assign(f,'Nhom_DT.inp'); {$I-} reset(f);{$I+} if IOResult>0 then begin rewrite(f);reset(f); end; fillchar(Dem,sizeof(Dem),0); readln(f,n);max:=0; for i:=1 to n begin read(f,x);Dem[x]:=Dem[x]+1; if x>max then max:=x; end; close(f); end; Chương trình tham khảo procedure xuly; var i,d:byte; begin assign(f,'Nhom_DT.out'); rewrite(f); for i:=1 to max if dem[i]>0 then inc(d); writeln(f,d); close(f); end; begin kt_docdl; xuly; End Bài 10: Phủ nhỏ Tên tệp chương trình: Phu.pas (Đề thi chọn HSG 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ó tọa độ 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 GV: Nguyễn Trương Tiên 17 Năm học: 2016-2017 Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG 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ụ: Phu.INP Phu.OUT 1 -1 Thuật toá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 khơng thể 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 Chương trình tham khảo Const Fi = ′PHU.INP′; Fo = ′PHU.OUT′; Procedure xuly; Max = 5000; Dd = 2; Var i,j,tmp,Count,Max:LongInt; Type Vec1 = Array [ Max,1 ] Of LongInt; Dung:Boolean; Vec2=Array[0 Max] Of LongInt; Begin Var n, P, Q, Min,Id : LongInt; Min:=0; A : Vec1; Chon : Vec2; If A[0,id]=0 Then Exit; Procedure Khoitao_dl; j:=0; Var i, L, R : LongInt; F : Text; Dung:=False; GV: Nguyễn Trương Tiên 18 Năm học: 2016-2017 Sáng kiến: ĐẾM ĐƠN GIẢN BẰNG THUẬT TỐN LÙA BỊ VÀO CHUỒNG Begin Count:=1; Id:=1; Assign(F, Fi); {$I-}Reset(F); {$I+} Chon[1]:=A[0,id]; if IOResult>o then If A[0, Dd] = Q-P Then begin Begin Rewrite(f);reset(f); Min:=1; Exit; end; End; Readln(F,n,P,Q); While Not Dung Do FillChar(A, SizeOf(A),0); Begin For i := To n Do Max:=j+A[j,Dd]; Begin For i:=j + To j + A[j,Dd] Do Readln(F,L,R); If (A[i, id]0) And (tt(i, j)>Max) If L Q Then A[0, Dd] := Q - P If Max=j+A[j,Dd] Then Exit Else A[0, Dd] := R - P; Else End Begin Else If L Q Then Dung := True; A[L - P, Dd] := Q - L End; Else A[L - P, Dd] := R - L; End; End; Min := Count; End; End; Close(F); Procedure IN_KQ; End; Var F : Text; i : LongInt; Function tinh_toan(u,v:LongInt):LongInt; Begin Begin Assign(F, FO); ReWrite(F); If A[u, Dd]+uMaxA then MaxA:=x; End; maxsl := 0; li:=0; For i := to MaxA {Duyet day chuong tim chuong co nhieu bo nhat} if A[i] > maxsl then... i←i+1; Nếu i>N chuyển Bước -Bươc 4: dem? ??1;j←0; -Bước 5: j←j+1; Nếu j>N chuyển đến Bước -Bước 6: Nếu ij A[i]=A[j] dem? ? ?dem+ 1; Quay lại Bước -Bước 7: Nếu dem> Max Max? ?dem gt←A[i]; Quay lại Bước GV:

Ngày đăng: 24/02/2021, 20:41

Xem thêm:

TỪ KHÓA LIÊN QUAN

w