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

(SKKN 2022) vận dụng mô hình tìm kiếm nhị phân và sử dụng các hàm tìm kiếm trong thư viện của ngôn ngữ lập trình c++ giúp học sinh giải quyết tối ưu một số dạng toán tìm kiếm nhằm nâng cao hiệu quả bồi dưỡng học sinh giỏi

22 127 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

Tiêu đề (SKKN 2022) Vận dụng mô hình tìm kiếm nhị phân và sử dụng các hàm tìm kiếm trong thư viện của ngôn ngữ lập trình C++ giúp học sinh giải quyết tối ưu một số dạng toán tìm kiếm nhằm nâng cao hiệu quả bồi dưỡng học sinh giỏi
Trường học Trường THPT Triệu Sơn 3
Chuyên ngành Tin học
Thể loại Sáng kiến kinh nghiệm
Năm xuất bản 2022
Thành phố Thanh Hóa
Định dạng
Số trang 22
Dung lượng 67,69 KB

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

Nội dung

Trong các chuyên đề ôn thi học sinh giỏi thì các chuyên đề mô hình thiết kế thuật toán chia để trị cùng với mô hình Quay lui, mô hình Tham lam, Quyhoạch động tạo thành bộ công cụ quan tr

Trang 1

1 MỞ ĐẦU

1.1 Lý do chọn đề tài.

Trong các chuyên đề ôn thi học sinh giỏi thì các chuyên đề mô hình thiết

kế thuật toán chia để trị cùng với mô hình Quay lui, mô hình Tham lam, Quyhoạch động tạo thành bộ công cụ quan trọng hỗ trợ thiết kế các thuật toán giảiquyết một số lượng lớn các bài tập một cách hiệu quả Trong đó, nổi bật vẫnphải kể tới một mô hình thiết kế dựa trên nguyên lí của thuật toán tìm kiếm nhịphân

Được đánh giá là một trong những thuật toán phổ biến nhất trong lĩnh vựcTin học, mô hình tìm kiếm nhị phân có hiệu quả đặc biệt về thời gian chạy cũngnhư sự rõ ràng về cách thức thiết kế thuật toán Có thể nói, tìm kiếm nhị phânkhông chỉ đơn thuần là thuật toán tìm kiếm mà còn là một mô hình tư duy thiết

kế thuật toán phổ biến Mô hình này dựa trên nguyên lí hoạt động của thuật toántìm kiếm nhị phân, đó là tìm kiếm một phần tử trên một dãy giá trị đã được sắpxếp bằng cách chia nhỏ miền tìm kiếm, sau mỗi lượt không gian tìm kiếm đượcthu gọn giảm bớt một nửa

Quá trình dạy tại các lớp mũi nhọn và ôn thi HSG cấp Tỉnh, tôi đã vận dụng

mô hình tìm kiếm nhị phân để giúp các em nhìn nhận một bài toán từ nhiều góc

độ khác nhau Qua đó có thể dễ dàng nhận ra việc áp dụng mô hình này để giải

bài toán nào đó Vì vậy, tôi đã chọn đề tài “Vận dụng mô hình tìm kiếm nhị phân và sử dụng các hàm tìm kiếm trong thư viện của ngôn ngữ lập trình C+ + giúp học sinh giải quyết tối ưu một số dạng toán tìm kiếm nhằm nâng cao hiệu quả bồi dưỡng học sinh giỏi” làm sáng kiến kinh nghiệm của mình trong

năm học 2021 – 2022 để trao đổi với đồng nghiệp Đây là một phương pháp tôi

đã thực hiện rất hiệu quả tại ngôi trường THPT Triệu Sơn 3, đồng thời cũng hyvọng cách làm này sẽ được hoàn thiện, bổ sung và nhân rộng trong các trườngTHPT khác trong Tỉnh

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

- Phát triển kĩ năng thiết kế thuật toán theo mô hình chia để trị, tức là giáoviên cần quan tâm kĩ tới khả năng nhận dạng bài toán, khả năng nhìn ra mô hìnhtìm nhị phân trong bài toán

- Vận dụng mô hình tìm kiếm nhị phân để đưa ra được thuật toán phù hợp.Bên cạnh đó, cần quan tâm tới yêu cầu học sinh đánh giá độ phức tạp thuật toán

- Tìm hiểu và vận dụng các hàm tìm kiếm trong thư viện của ngôn ngữ lậptrình C++ để giải quyết các bài toán tìm kiếm

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

- Mô hình tìm kiếm nhị phân

- Các hàm tìm kiếm trong thư viện của ngôn ngữ lập trình C++

- Một số dạng bài tập thi HSG các cấp

- Sự tư duy, ý thức học tập của học sinh ôn thi học sinh giỏi

Trang 2

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

- Điều tra khả năng tiếp cận môn Tin học lập trình của giáo viên THPT

- Điều tra khả năng tiếp cận môn Tin học lập trình của học sinh THPT

- Tham khảo tài liệu, nghiên cứu các đề thi, các bài toán thiên về tư duytoán học cơ bản chuyển về bài toán lập trình,

- Phương pháp thực nghiệm trên đối tượng là học sinh THPT

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.

Trong bối cảnh toàn ngành GD-ĐT đang nỗ lực đổi mới phương pháp dạyhọc theo hướng phát huy tính tích cực chủ động của học sinh trong hoạt động

học tập Điều 24.2 của Luật giáo dục đã nêu rõ: “Phương pháp giáo dục phổ thông phải phát huy tính tích cực, tự giác, chủ động, sáng tạo của học sinh, phù hợp với đặc điểm của từng lớp học, môn học; bồi dưỡng phương pháp tự học, rèn luyện kỹ năng vận dụng kiến thức vào thực tiễn, tác động đến tình cảm, đem lại niềm vui, hứng thú học tập cho học sinh ”.

Như vậy, chúng ta có thể thấy định hướng đổi mới phương pháp dạy học

đã được khẳng định, không còn là vấn đề tranh luận Cốt lõi của việc đổi mớiphương pháp dạy học ở trường phổ thông là giúp học sinh hướng tới việc họctập chủ động, chống lại thói quen học tập thụ động Với một số nội dung trong

đề tài này, học sinh có thể tự học, tự rèn luyện thông qua một số bài tập, dạngbài tập cụ thể

2.2 Thực trạng của vấn đề cần giải quyết

Qua thực tế giảng dạy ở trường THPT Triệu Sơn 3, tôi nhận thấy khi họcđến chương trình tin học lớp 11 đa số học sinh đều cho rằng đây là môn học khónhất trong các môn học, nhiều em còn sợ môn học này

Mô hình tìm kiếm nhị phân thường được dạy ngay sau giai đoạn học sinh họcxong phần kĩ thuật lập trình cơ bản Thời điểm này, học sinh đã có thể sử dụngngôn ngữ lập trình cùng với các công cụ có sẵn trong thư viện để thể hiện thuậttoán Tuy nhiên, khả năng tự mình nhìn nhận, đánh giá và thiết kế được mộtthuật toán cho bài toán mới còn hạn chế

Khi gặp các bài toán phải sử dụng kiểu dữ liệu lớn nhiều em lúng lúng.Việc giải các bài toán với kiểu dữ liệu lớn thực sự cần thiết cho các em khi làmcác bài toán lập trình trong chương trình Tin học phổ thông nói riêng và việcgiải quyết các bài toán thực tế nói chung

Thực tế cho thấy, các đề thi HSG của tỉnh Thanh Hóa và các tỉnh đều cócác bài tập tìm kiếm với số lớn Nếu học sinh không hiểu rõ và nhận biết tốt thìthường khi giải các bài tập này hay gặp nhiều sai sót hoặc không xử lý hết testtheo yêu cầu

Trang 3

2.3 Các giải pháp giải quyết vấn đề

2.3.1 Tổng quan về mô hình tìm nhị phân

Dựa trên thuật toán tìm kiếm nhị phân, mô hình thiết kế thuật toán dựa trêndạng này thường có phát biểu tổng quát dạng: Tìm kiếm một giá trị thoả mãnđiều kiện nào đó trên một miền giá trị được sắp thứ tự

Nhận dạng bài toán: Tìm một giá trị trên miền giá trị đã được sắp xếp.

Định hướng một số công việc cụ thể khi phân tích bài toán:

+ Lặp lại quá trình tìm kiếm với miền giá trị mới

Mặc dù thuật toán tìm kiếm nhị phân có nhiều cách cài đặt, ngoài ra thư việnSTL C++ cũng có các hàm hỗ trợ nhưng việc tự mình cài đặt và hiểu được môhình là rất quan trọng trong việc vận dụng thiết kế thuật toán theo mô hình tìmkiếm nhị phân

Dưới đây là một cách cài đặt phổ biến trên C++:

int solve(int a[], int x, int L, int R)

//tìm giá trị x trên dãy a[] từ chỉ số L tới chỉ số R

ans = mid;

break;

} if(a[mid]<x) L = mid+1;

else R = mid-1;

}

return ans;

}

Trang 4

2.3.2 Độ phức tạp thuật toán.

Người ta chứng minh được độ phức tạp tính toán của thuật toán tìm kiếmnhị phân trong trường hợp tốt nhất là O(1), trong trường hợp xấu nhất làO(logN) Mô hình tìm kiếm nhị phân chỉ thực hiện được với dãy đã được sắpxếp, nên nếu dãy chưa sắp xếp thì cần phải tính đến thời gian cho việc sắp xếplại dãy trước khi áp dụng tìm kiếm nhị phân

2.3.3 Các dạng bài tập tìm nhị phân

Dưới đây là một số dạng phát biểu chung của những bài toán có thể giảiquyết bằng mô hình tìm nhị phân

2.3.3.1 Dạng 1: Tìm kiếm nhị phân trên dãy (mảng) có sẵn.

Ở dạng này ta cần tìm phần tử có giá trị bằng x trên dãy a[] đã sắp xếp.Xét các ví dụ sau:

- Dòng thứ hai ghi N số nguyên A1, A2,… , A N(|A i|≤ 109)

- Q dòng tiếp theo mỗi dòng ghi một số nguyên X

85

2-15

Ý tưởng giải thuật 1: Tìm kiếm tuần tự Độ phức tạp là O(n)

Ý tưởng giải thuật 2: Tìm vị trí phần tử x trên dãy A đã sắp xếp tăng dần Nếu

không tồn tại x trong A, in ra -1

+ Tìm kiếm nhị phân: Vì dãy này đã được sắp xếp theo tiêu chí tăng dần, nên ta

cứ chia đôi ra tìm x Đầu tiên ta tìm vị trí ở giữa, so sánh x với giá trị ở vị trígiữa, nếu x bằng thì coi như đã tìm thấy Nếu x lớn hơn giá trị giữa thì ta phải

Trang 5

tìm phía bên phải của vị trí giữa, ngược lại thì tìm phía bên trái của vị trí giữa.

Độ phức tạp là O(log N)

Cài đặt hàm tìm kiếm trên C++

int bsearch(int a[], int l, int r, int x)

https://leetcode.com/problems/find-first-and-last-position-of-element-Cho dãy A được sắp xếp tăng dần A1, A2,… , A N Có Q truy vấn, mỗi truy vấn

là một số nguyên k: Với mỗi k, hãy in ra số đầu tiên bé nhất có giá trị lớn hơnhoặc bằng k gọi là P

- Dòng thứ hai ghi N số nguyên A1, A2,… , A N(|Ai|≤ 109)

- Q dòng tiếp theo mỗi dòng ghi một số nguyên x

Trang 6

Ý tưởng giải thuật 1: Tìm kiếm tuần tự Độ phức tạp là O(n)

Ý tưởng giải thuật 2 cải tiến : Tìm x đầu tiên nhỏ nhất có giá trị >=x

- ans = -1

- Khi L<=R

o giữa = (L+R)/2;

o Nếu a[giữa]<x thì tìm x trong [giữa+1, R]

o ngược lại tìm x trong [L, giữa-1], ans = giữa

- return ans

Cài đặt hàm tìm kiếm trên C++

int lower(int a[], int l, int r, int x)

https://leetcode.com/problems/find-first-and-last-position-of-element-Cho dãy A được sắp xếp tăng dần A1, A2,… , A N Có Q truy vấn, mỗi truy vấn

là một số nguyên k: Với mỗi k, hãy in ra số đầu tiên nhỏ nhất có giá trị > k gọi làP

Trang 7

- Dòng thứ hai ghi N số nguyên A1, A2,… , A N(|A i|≤ 109

4

48

Ý tưởng giải thuật tìm nhị phân:

 chốt cũng là một nghiệm tiềm năng ans = mid

 Thu hẹp miền tìm kiếm là nửa đầu dãy tức là [L, mid-1]

o Ngược lại:

 Tìm kiếm trên miền [mid+1, R]

Cài đặt hàm tìm kiếm trên C++

int upper(int a[], int l, int r, int x)

Trang 8

Sử dụng một số hàm tìm kiếm có sẵn trong thư viện STL của C++

- Hàm binary_search: là hàm tìm kiếm nhị phân có độ phức tạp là O(logn)

Cấu trúc của hàm như sau:

binary_search(a+1, a+n+1, x) có nghĩa là tìm x trong dãy a (đã được sắp xếp

tăng dần) từ vị trí 1 đến vị trí n Nếu có kết quả trả về true, ngược lại trả về false

binary_search(a, a+n, x): có nghĩa là tìm x trong dãy a (đã được sắp xếp tăng

dần) từ vị trí 0 đến vị trí n-1 Nếu có kết quả trả về true, ngược lại trả về false

- Hàm lower_bound(a+1, a+n+1, x) là cho vị trí đầu tiên của ô nhớ có giá trị

lớn hơn bằng x của mảng a(a[1],a[2]…., a[n])

- Hàm upper_bound(a+1, a+n+1, x) là cho địa chỉ đầu tiên của ô nhớ có giá trị

lớn hơn x của mảng a(a[1], a[2],…a[n])

2.3.3.1.2 Một số bài tập vận dụng trong các đề thi học sinh giỏi

Bài tập 1: Count x ( Nguồn Đề thi HSG tỉnh Lâm đồng 2015)

Cho dãy A gồm N phần tử A1, A2,… , A Nđã được sắp xếp tăng dần và Qtruy vấn, mỗi truy vấn gồm một số nguyên x yêu cầu đếm số lượng phần tử cógiá trị là x?

- Q dòng cuối, mỗi dòng ghi một số nguyên x

Output: Với mỗi truy vấn, hãy in kết quả trên một dòng.

Ví dụ:

10 3

1 2 2 3 4 4 4 5 6 62

49

230

Ý tưởng giải thuật: Với mỗi truy vấn:

- Tìm id1 là chỉ số vị trí x đầu tiên, id2 là chỉ số vị trí ngay sau x cuối cùng

 số lượng là id2-id1

- id1 = lower_bound; id2=upper_bound

Cài đặt hàm tìm kiếm trên C+

int countx(int a[], int l, int r, int x)

{

//Đếm trong dãy a từ a[l] đến a[r] số lượng phần tử x

int id1 = lower(a, l, r, x);

int id2 = upper(a, l, r, x);

Trang 9

return id2-id1;

}

Bài tập 2: COUNTONE.CPP (Nguồn: Đề thi HSG tỉnh Yên bái 2014)

Cho dãy A chỉ gồm các số nguyên 0, 1; Hãy đếm số lượng phần tử có giátrị 1 trong dãy đã được sắp xếp giảm dần

Input:

- Dòng đầu ghi số nguyên n là số lượng phần tử trong dãy (1 ≤ n ≤ 106)

- Dòng thứ hai ghi n số nguyên, mỗi số có giá trị là 0 hoặc 1

- Dữ liệu đảm bảo dãy đã được sắp xếp giảm dần

Output: Một số nguyên là số lượng phần tử 1 trong dãy

Ý tưởng giải thuật 2 : tìm nhị phân trực tiếp trên dãy

- Nhận xét: dãy toàn số 0, rồi toàn số 1  Tìm vị trí i thoả mãn a[i]<a[i-1]

o Nếu a[mid]=1 && a[mid+1]=0 thì ans=mid

o Ngược lại nếu a[mid]=1 && a[mid+1]!=0 thì tìm ở [mid+1,R]

o Ngược lại nếu a[mid]=0 và a[mid+1]=0 thì tìm ở nửa đầu [L,mid-1]

Độ phức tạp của thuật toán là O(logn)

Cài đặt hàm tìm kiếm trên C++

int countone(int a[], int l, int r)

{

int ans = 0;

while(l<=r)

{

Trang 10

Bạn hãy tính giúp cho admin xem có thể có bao nhiêu cách sắp xếp từngcặp đôi với nhau thỏa mãn?

Input:

- Dòng đầu tiên là N - số lượng người tham gia bữa tiệc và số K (N≤10^5,K≤10^9)

- Các dòng tiếp theo là chiều cao của N người tham gia bữa tiệc – không có

2 người nào có chiều cao giống nhau (Hi ≤ 10^9)

Trang 11

- Ta sắp xếp mảng chiều cao h thành dãy không giảm (tăng dần), vì nếu(a,b) là một cặp thì cặp (b,a) không được tính nữa

- Ta duyệt i từ 1 đến n-1, với mỗi i ta tìm: vị trí trái (left) là vị trí đầu tiêntrong đoạn từ [i+1, n] mà h[left]==h[i] +k Vị trí phải (right) là vị trí cuối cùngtrong đoạn từ [i+1, n] mà h[right]== h[i] +k Như vậy số cặp ghép với h[i] sẽ làright – left +1

- Độ phức tạp của thuật toán là O(nlogn)

Ta có thể dùng hàm lower_bound và upper_bound có sẵn trong thư viện C++

// tìm vị trí đầu tiên >= h[i] +k trong đoạn [i+1,n]

left= lower_bound(h+i+1, h+n+1, h[i]+k)- h

if (h[left!=h[i]+k) continue; // Nếu không có giá trị h[i]+k thì quay lên vòng lặp thực hiện tiếp

//Tìm vị trí cuối cùng bằng h[i]+k

right = upper_bound (h+i+1, h+n+1, h[i]+k) – h -1

res=res + (right – left +1)

}

Bài tập 4 Hẹn gặp (Nguồn: Đề thi HSG cấp Tỉnh Thanh Hóa năm 2016-2017)

Thành phố Gloaming (Hoàng hôn) nổi tiếng với đường dẫn vào công

viên thành phố Các bức tượng tuyệt đẹp theo chủ đề thần thoại Hy lạp – La mãđặt dọc theo con đường thẳng có một sức hút không cưỡng được với mọi khách

du lịch Còn khi những tia nắng cuối cùng trong ngày miễn cưỡng rời khỏi bầutrời thì sương mù dày đặc, như một tấm voan trắng mềm mại từ từ rũ xuống

Bây giờ đứng cách quá r mét là đã không nhìn thấy mặt nhau và các bức tượng

trở thành nơi lý tưởng cho các đôi nam nữ thanh niên hẹn hò

James Bond cần gặp gấp 2 điệp viên nội tuyến của mình để nhận các mậtbáo khẩn Không muốn 2 người này nhìn thấy nhau, Bond hẹn gặp mỗi người ở

một bức tượng sao cho khoảng cách giữa chúng lớn hơn r Trên đường có n bức tượng, bức tượng thứ i ở vị trí cách đầu con đường d i mét i = 1 ÷ n, 1 ≤ d 1 < d 2 <

.< d n ≤ 109

Yêu cầu: Hãy xác định James Bond có bao nhiêu cách chọn địa điểm.

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

- Dòng đầu tiên chứa 2 số nguyên n và r (1 ≤ n ≤ 3×105, 1 ≤ r ≤ 109)

Trang 12

- Dòng thứ 2 chứa n số nguyên d 1 , d 2 , , d n.

Kết quả: Đưa ra file văn bản HENGAP.OUT một số nguyên là số cách

chọn địa điểm tìm được

- Có ½ số test tương ứng với ½ số điểm có n ≤ 104

- Có ½ số test tương ứng với ½ số điểm có 104 < n ≤ 3×105

Ý tưởng giải thuật đề xuất:

- Dùng một vòng lặp For – do để duyệt i từ 1 đến n-1, trong đó với mỗi vịtrí i thì ta tìm kiếm nhị phân để tìm địa điểm j xa nhất thỏa mãn r+di < dj

Cài đặt giải thuật trên C++ (Trình bày chi tiết ở phần phụ lục)

2.2.3.2 Dạng 2: Tìm kiếm trên miền kết quả (Binary search the answer)

Dạng tìm một phần tử trên dãy được sắp xếp là dạng cơ bản quen thuộc Ta

có thể mở rộng việc tìm kiếm nhị phân trên miền kết quả Bắt đầu bằng miền tìmkiếm: là miền giá trị mà chắc chắn kết quả cần tìm sẽ thuộc vào đó Với mỗi lầntìm kiếm, chia đôi miền đó

Giả sử ta có hàm check(x) trả về true nếu kết quả của x là có thể, ngược lạitrả về false Với loại bài toán dạng này, ta thường tìm giá trị lớn nhất, nhỏ nhấtcủa x sao cho check(x)=true

- Nếu muốn tìm giá trị lớn nhất của x:

o Nếu check(x) là true thì check(y)=true với mọi y ≤ x

o Nếu check(x)=false, thì check(y)=false với mọi y ≥ x

- Nói cách khác, ta muốn giảm không gian tìm kiếm sử dụng hàm check ởtrên theo dạng sau: True – false

- Khi đó, cần tìm vị trí mà thay đổi từ True thành False bằng Tìm kiếm nhịphân

2.3.3.2.2 Một số bài tập vận dụng trong các đề thi học sinh giỏi

Bài tập 1: Nguồn: http://www.spoj.com/PTIT/problems/PTIT126J/

Có N cây gỗ, có chiều cao lần lượt là A[1], A[2], , A[n] Bạn cần lấy mộtlượng gỗ độ cao tối thiểu là M bằng cách chặt từ N cây theo cách như sau: chặttất cả những phần thừa của các cây có độ cao lớn hơn H Hãy tìm giá trị H lớnnhất để bạn có thể lấy được lượng gỗ tối thiểu là M

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

+ Dòng 1 chứa 2 số nguyên N (1<=N<=106) và M (1 <= M <= 2.109).+ Dòng 2 chứa N số nguyên A[1], A[2], …, A[n], là chiều cao mỗi cây gỗtương ứng (A[i] <= 109, i=1 N) Giả sử luôn tồn tại cách chặt

Ngày đăng: 05/06/2022, 10:23

HÌNH ẢNH LIÊN QUAN

2.3.1. Tổng quan về mô hình tìm nhị phân - (SKKN 2022) vận dụng mô hình tìm kiếm nhị phân và sử dụng các hàm tìm kiếm trong thư viện của ngôn ngữ lập trình c++ giúp học sinh giải quyết tối ưu một số dạng toán tìm kiếm nhằm nâng cao hiệu quả bồi dưỡng học sinh giỏi
2.3.1. Tổng quan về mô hình tìm nhị phân (Trang 3)

TỪ KHÓA LIÊN QUAN

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

w