1. Trang chủ
  2. » Giáo Dục - Đào Tạo

(SKKN 2022) chuyên đề tìm kiếm nhị phân và ứng dụng các hàm lower bound (), upper bound () trong bồi dưỡng học sinh giỏi tin học 11

27 112 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

Thông tin cơ bản

Định dạng
Số trang 27
Dung lượng 78,38 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Kiến nghị...20 SỞ GIÁO DỤC ĐÀO TẠO THANH HÓA TRƯỜNG THPT HOẰNG HÓA 2 SÁNG KIẾN KINH NGHIỆM TÊN ĐỀ TÀI CHUYÊN ĐỀ TÌM KIẾM NHỊ PHÂN VÀ ỨNG DỤNG CÁC HÀM LOWER_BOUND , UPPER_BOUND TRONG BỒI

Trang 1

MỤC LỤC

Trang

1 MỞ ĐẦU

1.1 Lí do chọn đề tài 1

1.2 Mục đích nghiên cứu 1

1.3 Đối tượng nghiên cứu 1

1.4 Phương pháp nghiên cứu .2

2 NỘI DUNG SÁNG KIẾN KINH NGHIỆM 2.1 Cơ sở lí luận của sáng kiến kinh nghiệm 2

2.1.1 Thuật toán tìm kiếm nhị phân 2

2.1.2 Khái niệm các hàm lower_bound(), upper_bound có sẵn trong C++ và những hệ quả của các hàm……… 5

2.1.3 Thuật toán chặt nhị phân theo kết quả ……… 6

2.2 Thực trạng vấn đề trước khi áp dụng sáng kiến kinh nghiệm …… 9

2.3 Các sáng kiến kinh nghiệm hoặc các giải pháp đã sử dụng để giải quyết vấn đề ……….10

2.3.1 . Hướng dẫn học sinh một số bài tập sử dụng thuật toán tìm kiếm Nhị phân và sử dụng hàm lower_bound(), upper_bound trong C++ ….10 2.3.2 Hướng dẫn học sinh một số bài tập sử dụng thuật toán chặt nhị phân theo kết quả……… 14

2.4 Hiệu quả của sáng kiến kinh nghiệm đối với hoạt động giáo dục, với bản thân, đồng nghiệp và nhà trường 19

3 KẾT LUẬN, KIẾN NGHỊ 3.1 Kết luận 20

3.2 Kiến nghị 20

SỞ GIÁO DỤC ĐÀO TẠO THANH HÓA

TRƯỜNG THPT HOẰNG HÓA 2

SÁNG KIẾN KINH NGHIỆM

TÊN ĐỀ TÀI CHUYÊN ĐỀ TÌM KIẾM NHỊ PHÂN VÀ ỨNG DỤNG CÁC HÀM LOWER_BOUND (), UPPER_BOUND () TRONG BỒI

DƯỠNG HỌC SINH GIỎI TIN HỌC 11

Người thực hiện : Trương Thị Quý Chức vụ: Giáo viên

SKKN thuộc lĩnh vực : Tin học

THANH HÓA, NĂM 2022

Trang 2

MỤC LỤC

Trang

1 MỞ ĐẦU

1.1 Lí do chọn đề tài 1

1.2 Mục đích nghiên cứu 1

1.3 Đối tượng nghiên cứu 1

1.4 Phương pháp nghiên cứu .2

2 NỘI DUNG SÁNG KIẾN KINH NGHIỆM 2.1 Cơ sở lí luận của sáng kiến kinh nghiệm 2

2.1.1 Thuật toán tìm kiếm nhị phân 2

2.1.2 Khái niệm các hàm lower_bound(), upper_bound có sẵn trong C++ và những hệ quả của các hàm……… 5

2.1.3 Thuật toán chặt nhị phân theo kết quả ……… 7

2.2 Thực trạng vấn đề trước khi áp dụng sáng kiến kinh nghiệm …… 9

2.3 Các sáng kiến kinh nghiệm hoặc các giải pháp đã sử dụng để giải quyết vấn đề……….10

2.3.1 . Hướng dẫn học sinh một số bài tập sử dụng thuật toán tìm kiếm nhị phân và sử dụng hàm lower_bound(), upper_bound trong C++ ………10

2.3.2 Hướng dẫn học sinh một số bài tập sử dụng thuật toán chặt nhị phân theo kết quả………14

2.4 Hiệu quả của sáng kiến kinh nghiệm đối với hoạt động giáo dục, với bản thân, đồng nghiệp và nhà trường………

20 3 KẾT LUẬN, KIẾN NGHỊ 3.1 Kết luận 20

Trang 3

3.2 Kiến nghị 21

Trang 4

Trong quá trình giảng dạy nhiều năm, tôi nhận thấy một số bài toán lập trình liênquan công việc tìm kiếm hay như đưa ra kết quả bài toán có thể áp dụng đượcthuật toán trên, đồng thời rèn luyện kĩ năng lập trình và khả năng tư duy cho họcsinh Do đó, tôi mạnh dạn đề xuất sáng kiến kinh nghiệm :

“ Chuyên đề tìm kiếm nhị phân và ứng dụng các hàm lower_bound (), upper_bound () trong bồi dưỡng học sinh giỏi tin học 11”.

1.2 Mục đích nghiên cứu

- Nghiên cứu các bài toán có dữ liệu lớn mà khi chúng ta sử dụng các

phương pháp như tìm kiếm tuần tự sẽ không xét hết được tất cả các trường hợpcủa bài toán

- Ứng dụng ngôn ngữ lập trình C++ vào những bài toán cụ thể để giải quyết

vấn đề

- Giúp học sinh giải quyết bài tập một chương trình có cấu trúc để giải một

bài toán trên máy tính

1.3 Đối tượng nghiên cứu

- Thuật toán tìm kiếm nhị phân

- Sử dụng hàm lower_bound(), upper_bound() có sẵn trong C++ để giải

quyết bài toán

- Thuật toán chặt nhị phân theo kết quả

- Một số bài toán cụ thể trong thực tế có áp dụng thuật toán

Trang 5

- Tìm hiểu khả năng vận dụng của từng đối tượng học sinh mỗi lớp dạy vềlập trình các bài toán để có phương pháp giảng dạy phù hợp

1.4 Phương pháp nghiên cứu

- Tìm hiểu thuật toán tìm kiếm nhị phân

- Tìm hiểu thuật toán chặt nhị phân theo kết quả

- Tìm hiểu các hàm lower_bound(), upper_bound có sẵn trong C++.

- Chọn lọc một số bài tập điển hình liên quan tới tìm kiếm và chặt nhị phântheo kết quả để minh họa, hướng dẫn học sinh luyện tập và thực hành

- Thu thập thông tin kết quả học tập về khả năng lập trình một số bài toán ởmột số lớp giảng dạy để có sự so sánh, đối chiếu thực nghiệm kết quả thực hiệncủa đề tài

- Tham khảo một số tư liệu trên internet và tài liệu của đồng nghiệp

2 NỘI DUNG SÁNG KIẾN KINH NGHIỆM

2.1 Cơ sở lí luận của sáng kiến kinh nghiệm.

2.1.1 Thuật toán tìm kiếm nhị phân:

- b3: Thực hiện công việc so sánh :

+ Nếu a[g]=X ta có kết quả ans= g : Đưa ra kết quả ans=g rồi kếtthúc bài toán

+ Nếu a[g]>X : X có thể thuộc đoạn bên trái của a[g] và thực hiện tìm

X, lúc này vị trí c thay đổi c=g-1

+ Nếu vị trí a[g]> X : X có thể nằm đoạn bên phải của a[g] và thựchiện tìm kiếm X, lúc này vị trí d thay đổi d=g+1

Công việc so sánh và gán các giá trị d, c, g sẽ được lặp đi lặp lại cho đến khi d>cthì dừng và đưa ra kết quả không tìm thấy X trong dãy hay in ra kết quả là -1

Trang 8

while (d <= c) { int g = (d + c)/2;

if (a[g] >= x) { kq = g;

for (int i=1; i<=n; i++) cin >> a[i];

sort(a+1, a+n+1); cout << tknp1(1,n,x); return 0;

}

2.1.1.3 Xét ví dụ 2 :

Cho dãy số nguyên a 1, a 2, a 3, , a n đã được sắp xếp không giảm và một số nguyên X Tìm vị trí k lớn nhất sao cho a[k] <X Nếu trong dãy không có k thì thông báo -1.

Ý tưởng :

Do k là vị trí lớn nhất mà a[k] < X

Nên vị trí k là kết quả kq = tknp1(1, n, x ) - 1.

Vd : cho dãy : 1, 3, 5, 6, 6, 6, 7, 9 X=6 nên vị trí k là 3 và a[k]=5<6 Mà hàm

tknp1(1, n, x) sẽ cho kq là 4 nên kq bài toán là tknp1(1, n, x) – 1 = 4-1=3

2.1.2 Khái niệm các hàm lower_bound(), upper_bound () có sẵn trong C++ và những hệ quả của các hàm :

Để thay thế cho thuật toán tìm kiếm nhị phân thì trong ngôn ngữ lập trình C++

có 2 hàm dùng sẵn là lower_bound(), upper_bound().

Trang 9

2.1.2.1 Hàm lower_bound(a+1,a+n+1,x) -a : cho ra vị trí đầu tiên trong mảng

a có giá trị > = x( từ vị trí 1 đến n), nếu không có x trong mảng a thì nó sẽ đưakết quả là (n+1)

Tương tự ta có thể sử dụng hàm này để đưa ra vị trí đầu tiên a[k]>= x từ vị trí i đến vị trí j : Hàm lower_bound(a+i, a+j+1, x) - a.

Áp dụng :

Cho dãy số nguyên a 1, a 2, a 3, , a n dãy đã được sắp xếp không giảm và một số nguyên X Tìm vị trí k nhỏ nhất sao cho a[k] >=X

- Ta dùng hàm : kq = lower_bound (a+1, a+n+1, x) - a

2.1.2.2 Hàm upper_bound(a+1,a+n+1,x)- a : cho ra vị trí đầu tiên trong mảng

a có giá trị > x ( từ vị trí 1 đến n), nếu không có x trong mảng a thì nó sẽ đưa kếtquả là (n+1)

Tương tự ta có thể sử dụng hàm này để đưa ra vị trí đầu tiên a[k]> x từ vị trí i đến vị trí j : Hàm upper_bound(a+i, a+j+1, x) - a.

Áp dụng :

Cho dãy số nguyên a 1, a 2, a 3, , a n dãy đã được sắp xếp không giảm và một số

nguyên X Tìm vị trí k nhỏ nhất sao cho a[k] >X

Ta dùng hàm : kq = upper_bound (a+1, a+n+1, x) – a

2.1.2.3 Hệ quả 1: Để đếm số lượng các phần tử trong dãy a 1, a 2, a 3, , a n có giátrị bằng x.Dãy đã được sắp xếp không giảm

U= lower_bound( a+1, a+n+1, y) - upper_bound( a+1, a+n+1, x) ;

U là giá trị cần tìm

2.1.2.5 Hệ quả 3: Để đếm số lượng các phần tử trong dãy a 1, a 2, a 3, , a n đã đượcsắp xếp không giảm và một số nguyên x Đếm xem có bao nhiêu phần tử có giátrị >x

V= n+1 - ( upper_bound(a+1,a+n+1,x) -a);

Trang 10

2.1.3 Thuật toán chặt nhị phân theo kết quả.

Ý tưởng thuật toán :

B1 : Đánh giá kết quả nằm ở đoạn nào ?

R = mid - 1; hoặc L=mid+1 ;

}else L = mid + 1; hoặc R= mid -1 ;

}

}

Hàm check(mid) là chương trình con kiểm tra xem với giá trị mid có thoã mãnyêu cầu đề ra không

Nếu kiểm tra hàm check(mid) đúng thì mid là ứng cử viên cho kết quả và gán

tạm thời kq = mid Tiếp tục đi tìm kết quả tối ưu hơn Nếu bài toán yêu cầu tìmkết quả nhỏ nhất thì R = mid -1 và ngược lại để tìm kết quả lớn nhất thì gán L =mid+1 ;

Trường hợp nếu hàm check(mid) nhận kết quả sai thì giá trị l nhận kết quả L =mid +1 nếu muốn tìm kết quả nhỏ nhất và ngược lại R = mid -1 nếu tìm kết quảlớn nhất

Xét ví dụ sau :

Bài 1 Dãy con Tên file: SUB.CPP

Cho một dãy số nguyên dương a 1 , a 2 , , a N (10 < N <= 10 5 ), a i <=10 9 với mọi i=1 N và một số nguyên dương S (S < 10 9 ).

Yêu cầu : Tìm độ dài nhỏ nhất của dãy con chứa các phần tử liên tiếp của dãy

mà có tổng các phần tử lớn hơn hoặc bằng S

Dữ liệu vào: Đọc từ file SUB.INP gồm 2 dòng, dòng 1 chứa N và S ở dòng đầu.

Dòng 2 chứa các phần tử của dãy

Dữ liệu ra: Kết quả ghi vào file SUB.OUT, chứa độ dài của dãy con tìm được.

Trang 11

- mid= (L+r)/2 : ứng cử viên của kết quả.

- Xây dựng mảng tổng tiền tố của mảng A là mảng sum

- Kiểm tra xem hàm check (int mid) : dãy con độ dài mid có thoã mãn tổng >=skhông

- Nếu ( sum[ j]- sum[ j- mid ] )>=s thì đoạn này thoã mãn yêu cầu, gán tạm thờikq=mid

- Và đi tìm kết quả tốt hơn thì gán r= mid-1 ;

Bài này có thể làm theo thuật toán tìm kiếm nhị phân và sự dụng 2 hàm

lower_bound(), upper_bound(), chuyển bài toán về tìm cặp (i, j) thoã mãn

sum[j] – sum[i-1] > = s hay tìm trong mảng sum có giá trị thoã mãn > =sum[i]+s không ?

Code tham khảo :

Trang 12

for (int x,i=1; i<=n; i++)

{ cin >> x; s[i] = s[i-1] + x;

2.2 Thực trạng vấn đề trước khi áp dụng sáng kiến kinh nghiệm

Trên cơ sở nhiều năm được phân công giảng dạy khối lớp 11, trườngTHPT Hoằng Hóa 2, tôi đã lưu lại kết quả học tập và sự tiến bộ của học sinh ởmỗi năm học ở một số lớp để có sự đối chiếu và rút kinh nghiệm

Bảng số liệu kết quả đạt được khi sử dụng kiến thức liên quan tới lập trìnhgiải các bài tập về tìm kiếm nhị phân và chặt nhị phân theo kết quả của học sinh lớp

11 năm học 2020 - 2021 khi chưa thực hiện đề tài:

STT Lớp Sĩ số Đạt yêu cầu Không đạt yêu cầu

Trang 13

* Ưu điểm:

+ Đa số học sinh đã hiểu khái niệm cơ bản về thuật toán tìm kiếm

+ Một số em học sinh đã biết cách sử dụng thuật toán tìm kiếm nhị phân đểgiải bài tập

2.3 Các sáng kiến kinh nghiệm hoặc các giải pháp đã sử dụng để giải quyết vấn đề:

2.3.1 Hướng dẫn học sinh một số bài tập sử dụng thuật toán tìm kiếm

Nhị phân và hàm lower_bound(), upper_bound () trong C++

Bài tập 1 : Cho dãy số nguyên a 1, a 2, a 3, , a n Hãy đếm xem trong dãy số đã cho

có bao nhiêu cặp số ai, aj với i<j thoã mãn ai +aj =0

2 chứa các phần tử của dãy có |ai |<= 2.109

Dữ liệu ra: Kết quả ghi vào file count.out, một số nguyên duy nhất là số lượng

- Khắc phục bằng cách ta sự dụng hàm lower_bound(), upper_bound().

- a[i] +a[j]=0 nên a[i]= - a[j] chuyển về bài toán tìm kiếm đơn giản với x= -a[i]

Code tham khảo :

#include <bits/stdc++.h>

#define N int(1e5)

using namespace std;

Trang 14

Bài tập 2 : Bài 2 Kết bạn Tên file: friend.cpp

Theo quan niệm của người Á Đông cổ, mỗi cá nhân khi sinh ra đều ứng vớimột ngôi sao, được gọi là sao chiếu mệnh Các hoạt động của cá nhân đều bị chiphối bởi ngôi sao này, kể cả quá trình kết bạn – hẹn hò Theo thuyết Âm dương– Ngũ hành, hai người chỉ có thể tạo lập mối quan hệ bền vững khi các sao chiếumệnh của họ không có các thuộc tính tương khắc Qua hàng nghìn năm quan sát

và chiêm nghiệm, các chiêm tinh gia đã ghi nhận được n sao và hầu hết các tính

chất tương sinh – tương khắc giữa chúng Để có thể nhanh chóng đáp ứng nhu

cầu kiểm tra độ tương hợp của các sao, hiệp hội ABS (Association of Broker for

Single) tạo lập cơ sở dữ liệu ghi nhận tính chất của tất cả các sao đã khảo sát

được Trong cơ sở dữ liệu này, các sao được đánh số từ 1 tới n; sao thứ i có một giá trị s i thể hiện khả năng thích nghi của sao gọi là độ thích nghi Hai sao khácnhau có thể có cùng độ thích nghi Thông qua độ thích nghi của các sao, người

ta xác định khả năng tương hợp của chúng Khả năng tương hợp của 2 sao đượctính bằng tổng 2 độ thích nghi của chúng

sao và số nguyên B Hãy xác định số lượng các cặp sao (i, j) với i < j và s i + s j =

B

Trang 15

Dữ liệu: Vào từ file văn bản FRIEND.INP:

Dòng đầu tiên ghi 2 số nguyên n, B (2 ≤ n ≤ 105, |B| ≤ 109),

Mỗi dòng trong n dòng tiếp theo ghi một số nguyên là độ thích nghi của

một sao, độ thích nghi có trị tuyệt đối ≤ 109

Kết quả: Đưa ra file văn bản FRIEND.OUT một số nguyên – số lượng cặp

sao có độ tương hợp B tìm được.

Ví dụ: Trong 5 sao với độ thích nghi 3, 5, 6, 5, 3 có 4 cặp có khả năng tương

hợp bằng 8

FRIEND.IN P

FRIEND.OU T

+ Tìm vị trí đầu tiên của (b-s[i]) trong đoạn s[1] … s[i-1] là vt1

+ Tìm vị trí cuối cùng của (b-s[i]) trong đoạn s[1] … s[i-1] là vt2

int u=lower_bound(a+1,a+i,k)-a;

int v=upper_bound (a+1,a+i,k)-a-1;

ans+=v-u+1;

Trang 16

} cout << ans<< endl;

return 0;}

Bài tập 3: Đếm tam giác Tên file: TRIANGLE.CPP

Cho 3 dãy số dương A, B, C cùng có N phần tử Hãy đếm xem có bao nhiêu bộ

3 số A[i], B[j] và C[k] mà 3 số này là 3 cạnh của 1 tam giác

Dữ liệu vào: từ file TRIANGLE.INP với cấu trúc:

- Dòng đầu chứa số nguyên n (n <= 1000)

- Dòng thứ hai chứa các số A1, A2, , An

- Dòng thứ ba chứa các số B1, B2, , Bn

- Dòng thứ tư chứa các số C1, C2, , Cn

Các số ai, bi, ci đều không vượt quá 104 và được ghi cách nhau bởi dấu cách

Dữ liệu ra: file văn bản TRIANGLE.OUT gồm một số S duy nhất là số lượng

Trang 17

int a[N+5],b[N+5],c[N+5];

int n, ans;

int main() { freopen("humberger.inp","r",stdin);

freopen("humberger.out","w",stdout);

cin >> n;

for (int i=1; i<=n; i++) cin >> a[i];

for (int i=1; i<=n; i++) cin >> b[i];

for (int i=1; i<=n; i++) cin >> c[i];

sort(c+1,c+n+1);

for (int i=1; i<=n; i++) for (int j=1; j<=n; j++) {

Ở đầu ra của một dây chuyền sản xuất trong nhà máy ZXY có một máy xếp tựđộng Sau khi kết thúc việc gia công trên dây chuyền, các sản phẩm sẽ đượcxếp vào các hộp có cùng dung lượng M Sản phẩm rời khỏi dây chuyền đượcxếp vào hộp đang mở (khi bắt đầu ca làm việc có một hộp rỗng được mở sẵn)

Trang 18

nếu như dung lượng của hộp còn đủ để chứa sản phẩm Trong trường hợp ngượclại, máy sẽ tự động đóng nắp hộp hiện tại, cho xuất xưởng rồi mở một hộp rỗngmới để xếp sản phẩm vào Trong một ca làm việc có n sản phẩm đánh số từ 1đến n theo đúng thứ tự mà chúng rời khỏi dây chuyền Sản phẩm thứ i có trọnglượng là ai, i = 1, 2, …, n Ban Giám đốc nhà máy qui định rằng sản phẩm xuấtxưởng của mỗi ca làm việc phải được xếp vào trong không quá k hộp

Yêu cầu: Hãy giúp người quản đốc của ca làm việc xác định giá trị M nhỏ nhấtsao cho số hộp mà máy tự động cần sử dụng để xếp dãy n sản phẩm xuất xưởngcủa ca không vượt quá số k cho trước

Dữ liệu: Vào từ file văn bản ZXY.INP:

• Dòng đầu tiên chứa hai số nguyên n và k, (1 <= k <= n <= 15000);

• Dòng thứ i trong n dòng tiếp theo chứa số nguyên dương ai (ai <= 30000), i

=1, 2, …, n

Các số trên một dòng cách nhau ít nhất một dấu cách

Kết quả: Ghi ra file ZXY.OUT một số nguyên duy nhất là dung lượng của hộp

Ví dụ:

Ý tưởng: sử dụng chặt nhị phân theo kết quả

- l = max(ai); r = a1 + a2 + … + an chặt nhị phân trên đoạn [l, r]

mid = ( l+ r)/2, với mỗi giá trị mid ta kiểm tra xem có số lượng hộp cần dùng có

< = k, nếu đúng thì mid thoã mãn và đi tìm tiếp kết quả tốt hơn theo yêu cầu

Code tham khảo

#include <bits/stdc++.h>

#define N 15000 using namespace std;

int n,k,ans=0,sum=0;

Ngày đăng: 06/06/2022, 19:18

TỪ KHÓA LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w