SỞ GIÁO DỤC VÀ ĐÀO TẠO THANH HÓATRƯỜNG THPT NHƯ THANH SÁNG KIẾN KINH NGHIỆM ỨNG DỤNG THUẬT TOÁN CHẶT NHỊ PHÂN ĐỂ GIẢI MỘT SỐ BÀI TOÁN TÌM KIẾM Người thực hiện: Lê Thị Liễu Chức vụ: Giáo
Trang 1SỞ GIÁO DỤC VÀ ĐÀO TẠO THANH HÓA
TRƯỜNG THPT NHƯ THANH
SÁNG KIẾN KINH NGHIỆM
ỨNG DỤNG THUẬT TOÁN CHẶT NHỊ PHÂN
ĐỂ GIẢI MỘT SỐ BÀI TOÁN TÌM KIẾM
Người thực hiện: Lê Thị Liễu Chức vụ: Giáo viên
SKKN thuộc lĩnh vực (môn): Tin học
THANH HOÁ NĂM 2018
Trang 2MỤC LỤC
1 MỞ ĐẦU 1
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 1
2 NỘI DUNG……… … 2
2.1 Cơ sở lý luận 2
2 Thực trạng vấn đề 2
2.3 Ứng dụng thuật toán “Chặt nhị phân” 3
2.4 Hiệu quả 31
3 Kết luận, Kiến nghị 32
Trang 31 MỞ ĐẦU 1.1 Lí do chọn đề tài
Các bài toán tìm kiếm chiếm phần lớn trong các bài tập của Tin học, Có nhiều phươngpháp tìm kiếm để giải quyết bài toán đó trong đó tìm kiếm nhị phân là phương pháp tốt vìthời gian thực hiện nhanh
Thuật toán tìm kiếm nhị phân lại chỉ được trình bày ngắn gọn, sơ lược trong sách giáokhoa 10, 11 và không có ví dụ vận dụng dẫn đến học sinh khó có thể ứng dụng để làm cácbài tập
Trên thực tế khi gặp dạng toán tìm kiếm học sinh có thể dễ dàng tìm ra cách giảinhưng chưa tìm ra được cách giải tối ưu để lấy được hết điểm Đó là những lí do để tôi chọn
đề tài “ỨNG DỤNG THUẬT TOÁN CHẶT NHỊ PHÂN ĐỂ GIẢI MỘT SỐ BÀI TOÁNTÌM KIẾM”
1.2 Mục đích nghiên cứu
Giúp học sinh vận dụng thuật toán chặt nhị phân để giải được một số bài toán
1.3 Đối tượng nghiên cứu
- Thuật toán chặt nhị phân
- Một số ví dụ vận dụng, đánh giá độ phức tạp của thuật toán
1.4 Phương pháp nghiên cứu
- Nghiên cứu sách, báo, tài liệu điện tử
- Áp dụng vào giảng dạy và bồi dưỡng HSG Tin học 11
Trang 42 NỘI DUNG 2.1 Cơ sở lý luận
Bài toán tìm kiếm dạng đơn giản SGK lớp 10:
Cho dãy A gồm N số nguyên khác nhau: a1, a2,…,aN và một số nguyên K Cần biết có hay không chỉ số i mà ai=K (1<=i<=N) Nếu có hãy cho biết chỉ số đó.
Ý tưởng thuật toán tìm kiếm chị phân: Sử dụng tính chất dãy A là dãy số tăngdần, ta tìm cách thu hẹp nhanh phạm vi tìm kiếm sau mỗi lần so sánh khóa với số hạngđược chọn Để làm điều đó ta chọn số hạng Agiua ở giữa dãy để so sánh với K, trong đóGiua=[N+1] div 2
Khi đó chỉ xảy ra một trong ba trường hợp sau:
- Nếu Agiua=k thì giua là chỉ số cần tìm Việc tìm kiếm kết thúc
- Nếu Agiua>k thì việc tìm kiếm tiếp theo chỉ xét trên dãy A1, A2, …, Agiua-1 (Phạm vitìm kiếm mới bằng khoảng một nửa phạm vi tìm kiếm trước đó)
- Nếu Agiua<k thì việc tìm kiếm tiếp theo chỉ xét trên dãy Agiua+1, Agiua+2,…, AN
Quá trình trên sẽ được lặp lại một số lần cho đến khi hoặc đã tìm thấy khóa K trongdãy hoặc phạm vi tìm kiếm bằng rỗng
Đánh giá độ phức tạp:
- Thuật toán tìm kiếm nhị phân có độ phức tạp: O(logN),
- Tìm kiếm tuần tự độ phức tạp: O(N)
Tuy nhiên chỉ áp dụng tìm kiếm nhị phân khi dãy đã sắp xếp nên chúng ta thường sửdụng thuật toán sắp xếp nhanh (Qsort) với độ phức tạp O(NlogN) để sắp xếp dãy trướcđó
2.2 Thực trạng vấn đề.
Thực tế trong quá trình giảng dạy,khi gặp một bài toán tìm kiếm các em chỉ mới đưa rađược cách giải thông thường mà chưa tìm được phương pháp giải tối ưu
Trang 5Khi học xong thuật toán tìm kiếm nhị phân ở SGK lớp 10 các em hầu như không biếtvận dụng vào các bài toán, nguồn tài liệu tham khảo lại ít nên học sinh không hình thành được tưduy giải bài toán
2.3 Ứng dụng Thuật toán chặt nhị phân
Bài 1: Cho dãy A có N số Tìm số lượng các số có giá trị nhỏ hơn số nguyên M
Dữ liệu vào: Tệp ‘slbehon.inp’
- Dòng đầu tiên chứa số nguyên N cho biết số lượng phần tử của mảng A
- Dòng thứ hai chứa N số nguyên cách nhau
- Dòng thứ ba chứa số lượng Test Q
- Mỗi dòng Q tiếp theo chứa số nguyên M
Dữ liệu ra: Tệp ‘slbehon.out’:
- Đối với mỗi truy vấn số lượng các số có giá trị nhỏ hơn M cho test đó
1 4 10 5 64
23511
1125
Trang 6Cách 1: Xây dựng 1 hàm để đếm số lượng phần tử trong mảng A có giá trị bé hơn
M, hàm này được viết thường là duyệt tuần tự từ A1 đến AN, so sánh Ai với M và tăng biếnlưu giá trị đếm Chương trình được viết như sau:
Cách 2: Ta thực hiện sắp xếp mảng đã cho bằng thuật toán Qsort và áp dụng kỷ thuật
“chặt nhị phân” để xác định chỉ số cuối cùng của phần tử nhỏ hơn M Đôh phức tạp:O(Nlogn)
program So_luong_be_hon;
const fi='slbehon.inp';
fo='slbehon.out';
nmax=100000;
Trang 7var a:array[1 nmax] of longint;
while a[i]<k do inc(i);
while a[j]>k do dec(j);
Trang 9Dữ liệu vào: Tệp ‘chenhlech.inp’:
- Dòng đầu tiên là N - số lượng dãy số và số nguyên K (N≤105, K≤109)
- Dòng tiếp theo chứa N số nguyên trong dãy (A[i] ≤ 109)
Dữ liệu ra: Tệp ‘chenhlech.out’
Trang 11for i:=1 to n do read(f,a[i]);
while a[i]<x do inc(i);
while x<a[j] do dec(j);
Trang 13Bài 3 Chọn quân bài
Cho một tập N quân bài, mỗi quân chứa một số nguyên dương Bạn cần phải chọn ra
ba quân bài sao cho tổng các số trên 3 quân bài gần với số M nhất và không vượt quá M
Dữ liệu vào: Tệp ‘quanbai.inp’:
Dòng 1 chứa 2 số N và M (N <=100, M <= 500000)
Dòng 2 chứa N số nguyên dương, mỗi số không quá 100000
Dữ liệu ra: Tệp ‘quanbai.out’:
Trang 14In ra tổng 3 quân gần M nhất và không vượt quá M.
Input luôn đảm bảo tồn tại đáp số
Trang 15program quanbai;
Trang 18repeat
while a[i]<k do inc(i);
while a[j]>k do dec(j);
Trang 19Bài 4 Có hộp N kẹo và mỗi hộp chứa A[i] cái kẹo Số thứ tự của các viên kẹo được
đánh số từ 1,2,3, đến hết Cho biết thứ tự của viên kẹo, hãy chỉ ra viên kẹo đó thuộc hộp kẹo thứ mấy
Dữ liệu vào: Tệp ‘Thutukeo.inp’
- Dòng đầu tiên sẽ chứa N (Số hộp)
- Dòng tiếp theo cho biết số kẹo trong hộp thứ i
Trang 20- Dòng tiếp theo sẽ chứa Q (Số lần test).
- Q dòng tiếp theo mỗi dòng chứa 1 giá trị nguyên là thứ tự của viên kẹo
Hộp đầu tiên sẽ có các viên kẹo thứ tự: 1, 2Hộp thứ hai sẽ có các viên kẹo chỉ số: 3, 4, 5
Ý tưởng: Xây dựng mảng S với ý nghĩa S[i] là tổng các phần tử từ A[1] đến A[i] Thựchiện tìm kiếm nhị phân trên mảng S
Trang 22Bài 5 Cho 1 xâu S chỉ chứa các ký tự in thường ['a'-'z'] và 1 số nguyên K Hãy tìm các xâu
con liên tiếp của S có trọng lượng bằng K
Trọng lượng của 1 ký tự được tính như sau: ['a']=1; ['b']=2; ['c']=3,…['z']=26
Trọng lượng của xâu S được tính là tổng trọng lượng các ký tự có trong xâu S
Dữ liệu đầu vào: Tệp ‘timxaucon.inp’:
Dòng đầu tiên chứa số lượng các trường hợp cần kiểm tra T Với mỗi test dữ liệu đượccho trên 2 dòng, dòng đầu là số nguyên K và dòng sau là xâu S
Dữ liệu ra: Tệp ‘timxaucon.out’
In ra số lượng các xâu con có trọng lượng bằng K, mỗi số trên 1 dòng
Giới hạn:1<=T<=20; 1<=K<=26*|S| ; 1<=|S|<=1000000
Timxaucon.inp Timxaucon.out
Trang 235abcdef4abcdef
Trang 26writeln(f1,d);
end;
close(f1);
end
Bài 6 Trong một chuyến đi đến siêu thị CoopMart, Tân muốn mua một số món hàng
cho bạn bè và người thân của mình
Siêu thị này có một số quy tắc kỳ lạ Nó chứa n các sản phẩm khác nhau được đánh số
từ 1 đến n Mặt hàng thứ i có giá cơ bản không đổi là bi Nếu Tân mua K mặt hàng với chỉ
số x1, x2, , xk, thì giá của sản phẩm xj là bxj + xj* k với 1 ≤ j ≤ k Nói cách khác, giá của một mặt hàng bằng với giá căn bản cộng với chỉ số nhân với hệ số k
Tân muốn mua càng nhiều đồ càng tốt mà không phải trả nhiều tiền hơn một số SP Lưu ý rằng mỗi món hàng chỉ được mua 1 lần Hãy giúp Tân chọn cách mua với nhiều mặt hàng nhất
Dữ liệu vào: Tệp ‘muahang.inp’
- Dòng đầu tiên chứa hai số nguyên n và SP (1 ≤ n ≤ 105 và 1 ≤ SP ≤ 109) - số lượng các mặt hàng trên và số tiền tối đa Tân có thể mua
- Dòng thứ hai chứa n số nguyên b1, b2, , bn(1 ≤ bi ≤ 105) - giá trị cơ bản của các mặt hàng
Dữ liệu ra: Tệp ‘muahang.out’
- In hai số nguyên k, T là số lượng tối đa các hàng mà Tân có thể mua và tổng chi phí tối thiểu để mua những mặt hàng k
Muahang.inp Muahang.out Giải thích test
3 11 2 11 Trong ví dụ này, Tân không thể lấy cả ba mặt hàng
bởi vì giá của mỗi mặt hàng lần lượt là [5, 9, 14] và
Trang 272 3 5 tổng chi phí của nó 28 Nếu Tân chỉ mua hai mặt
hàng, thì chi phí sẽ là [4, 7] và tổng chi phí là 11
Bài 6 Vào đêm Noel, Hòa cùng M người bạn của mình lên kế hoạch để đi chơi.
Nhà của Hòa và các bạn của cô nằm trên cùng 1 con đường, các nhà được đánh vị trí từ 1đến N, mỗi nhà cách nhau 1 mét Nhà của Hòa ở vị trí 1 và địa điểm vui chơi ở vị trí N Nhà
M người bạn ở các vị trí a1, a2, , aM Ngoài ra trên tuyến đường còn có P trạm xe buýt tạicác vị trí b1, b2, , bP Từ nhà mình, Hòa lần lượt đi đến nhà của các bạn mình theo kếhoạch Cô có thể đi bằng taxi hoặc xe buýt Với taxi, cô có thể bắt từ bất kì vị trí nào, giácủa taxi là T đồng/mét Với xe buýt, cô chỉ có thể bắt từ trạm này và đi đến một trạm khác,giá của xe buýt là B đồng/lượt không phân biệt khoảng cách Bạn hãy giúp Hòa tìm cách điđón tất cả các bạn và đến điểm vui chơi với số tiền phải trả là ít nhất
Yêu cầu: Cho biết số nhà trên đường, các nhà phải đến đón, số trạm xe buýt và số tiền
đi xe taxi, xe buýt, bạn hãy tìm cách đi sao cho đến thăm đúng thứ tự các nhà và đến vị trí Nvới số tiền ít nhất
Dữ liệu nhập: Tệp ‘Taxibuyt.inp’
- Dòng thứ nhất chứa các số nguyên N, M, P, T, B là số nhà, các nhà phải đón, số
trạm xe buýt và số tiền đi taxi, xe buýt (1 ≤ N ≤ 109 | 0 ≤ M,P ≤ 105 | 1 ≤ T,B ≤ 104)
- Dòng thứ hai chứa M số nguyên là thứ tự các nhà phải đến, số thứ ai là vị trí của nhàthứ i (1 ≤ ai ≤ N) Dữ liệu cho đảm bảo không có 2 nhà trùng vị trí
- Dòng cuối cùng chứa P số nguyên là vị trí các trạm xe buýt theo thứ tự tăng dần, sốthứ bi là vị trí của trạm thứ i, mặc định có trạm ở vị trí 1 và N (1 ≤ bi ≤ N)
Dữ liệu xuất: Tệp ‘taxibuyt.out’
In ra 1 số nguyên duy nhất là số tiền ít nhất phải trả
Taxibuyt.inp Taxibuyt.out Giải thích test
Trang 2810 2 2 1000 2000
5 8
4 7
8000 - Đầu tiên Hòa đi xe buýt từ 1 đến 4
- Sau đó đi taxi từ 4 đến 5, 5 đến 8 và 8 đến 10Tổng số tiền là 2000+1000+3000+2000=8000 đồng
Ý tưởng: Thực hiện tìm kiếm nhị phân để tìm ra điểm xe buýt gần nhất với từng địa điểm nhà bạn của Hòa và lưu vào mảng TB
Để tìm chi phí rẻ nhất cho cách đi từ nhà thứ i đến nhà i+1 ta chỉ cần so sánh giá trị (khoảng cách giữa 2 nhà)* số tiền đi taxi và (khoảng cách từ điểm 2 xe buýt gần nhất tới 2 ngôi nhà)* số tiền đi taxi + số tiền đi 1 lượt xe buýt
Ví dụ như hình dưới: Ký hiệu B1, B2 là vị trí nhà các bạn của Hòa; N1, N2 là vị trí cácđiểm xe buýt gần nhất với 2 ngôi nhà thì ta so sánh (abs(B1-N1)+abs(B2-N2))*Số tiền đi taxi +Số tiền cho mỗi lượt đi xe buýt và (B2-B1)*Số tiền đi taxi
N 2
Trang 31nhau, nông dân John muốn đặt mỗi con bò vào một cái cọc, sao cho khoảng cách nhỏ nhất
giữa hai con bò bất kì là lớn nhất Hãy tìm giá trị lớn nhất này.
Dữ liệu vào: Tệp ‘conbo.inp’:
- Dòng đầu tiên gồm hai số nguyên dương N và C (2 ≤ C ≤ N ≤ 100000)
- N dòng tiếp theo, mỗi dòng chứa một số nguyên xi mô tả vị trí của một cây cọc (0 ≤
xi ≤ 109)
Dữ liệu ra: Tệp ‘conbo.out’
- In ra giá trị lớn nhất của khoảng cách nhỏ nhất giữa hai con bò bất kì
'conbo.inp' 'conbo.out' Giải thích test
Trang 32procedure sort(l,h: longint);
var i,j,khoa,tam: longint;
while a[i]<khoa do inc(i);
while khoa<a[j] do dec(j);
Trang 34Bài 1 Bảo tồn động vật hoang dã (Nguồn bài: thầy Lê Minh Hoàng)
Một khu bảo tồn động vật có N địa điểm và các đường đi hai chiều nối các địa điểm
đó, địa điểm thứ i có nhiệt độ là ti, giữa hai địa điểm bất kỳ có nhiều nhất là một đường đinối chúng Người ta muốn di chuyển một loài động vật quý hiếm từ địa điểm A tới địađiểm B, tuy nhiên nếu chênh lệch về nhiệt độ giữa hai địa điểm liên tiếp trên đường đi làquá cao thì loài động vật này rất có thể bị chết
Yêu cầu: Hãy chỉ ra một hành trình mà độ lệch nhiệt độ lớn nhất giữa hai địa điểm liêntiếp bất kỳ trên đường đi là cực tiểu
Dữ liệu vào: Đọc từ file MOVE.INP
- Dòng 1: Chứa ba số N, A, B (2 ≤ N ≤ 200; A#B)
- Dòng 2: Chứa N số tự nhiên t1, t2, , tN ("i: 0 ≤ ti ≤ 20000)
- Các dòng tiếp theo, mỗi dòng chứa hai số nguyên dương u, v cho biết giữa hai địađiểm u và v có đường đi nối chúng
Trang 35Kết quả: Ghi ra file MOVE.OUT ghi một số nguyên là độ lệch nhiệt độ lớn nhất giữa hai địa điểm liên tiếp bất kỳ trên đường đi tìm được, nếu không tồn tại đường đi thì dòng này ghi số -1.
Bài 2 DGOLD - Chia vàng – Nguồn Spoj.com
Chuyện kể lại rằng, trong một lần thám hiểm hang động, Aladdin và thần đèn pháthiện một kho báu cổ xưa gồm N thỏi vàng ròng Vẫn còn tiếc rẻ vì ngày trước ở trong hangthần không thó được món gì ngoài cây đèn cũ nát, Aladdin quyết tâm lần này sẽ mang hếtvàng về Ngặt nỗi kho báu này bị nguyền: Nếu muốn đem K thỏi vàng ra khỏi hang thì Kthỏi vàng này phải được chia thành 2 phần có khối lượng bằng nhau mà không được cắt, đậpthỏi vàng nào ra cả Nếu không làm đúng thì hang sẽ sập xuống chôn vùi tất cả, đến thầnđèn cũng không cứu được
Trang 36Thần đèn dù tài phép vô biên nhưng tính toán lại rất kém, chỉ có thể hô biến ra một cáicân ký chứ không chọn được vàng Aladdin cũng không hơn gì (lớn lên trên đường phố mà).Tuy nhiên Aladdin lại không chịu ra khỏi hang một khi chưa đem được lượng vàng nhiềunhất về Thần đèn đang ngán ngẩm không biết khi nào Aladdin mới chọn vàng xong thì khỉAbu xuất hiện Nhanh như thoắt Abu đã chọn xong vàng và chia thành 2 túi có khối lượngđúng bằng nhau.Abu lại còn chọn được lượng vàng nhiều nhất nữa Trong lúc Aladdinmừng hớn hở (vì bắt được vàng) thì thần đèn do chậm hiểu vẫn còn thắc mắc không biếtmột túi có bao nhiêu vàng Hãy giúp thần đèn tìm con số này.
Input: Dòng đầu ghi số N– số thỏi vàng trong kho báu
N dòng tiếp theo, dòng thứ i ghi số nguyên dương Mi là khối lượng của thỏi vàng i(tính theo gam)
Bài 3 VOGCDSUM - Tổng ước chung lớn nhất – Nguồn Spoj.com
Giáo sư Honest là một tay bịp bợm có hạng trong giới khoa học Ngày hôm qua, hắnvừa tuyên bố rằng đã phát minh ra thuật toán tính ước chung lớn nhất của một dãy số có độphức tạp O(1/N), tức là input càng lớn thì thuật toán chạy càng nhanh
Trong báo cáo khoa học của mình, Honest bày ra thí nghiệm như sau:
Trang 37Cho một dãy số gồm N số nguyên dương Honest tính tổng của các ước chung lớn nhất của tất cả các dãy con liên tiếp của dãy số trên (dãy con liên tiếp của một dãy số N phần tử được định nghĩa là dãy con chứa phần tử thứ L, L + 1, , R với 1 ≤ L ≤ R ≤ N)
Honest tuyên bố rằng hắn có thể thực hiện thao tác vừa rồi trong O(N) bằng cách ápdụng thuật toán tính ước chung lớn nhất của một dãy số trên tất cả N * (N + 1) / 2, tức làO(N2), dãy con liên tiếp của dãy số Vì thế, thuật toán của hắn ta có độ phức tạp là O(1 / N)
"Không thể nào có chuyện như vậy!!!" Hội đồng khoa học của diễn đàn VNOI muốnlật tẩy trò lừa trẻ con của Honest Tuy nhiên thì đầu tiên họ cần tìm ra cách để thực hiện lạithí nghiệm của Honest với tốc độ nhanh nhất có thể Các bạn hãy giúp in ra số dư của kếtquả thí nghiệm mà Honest đã tiến hành khi chia cho 109 + 7 nhé
Trang 392.4 Hiệu quả
2.4.1 Đối với học sinh
Giúp học sinh nắm bắt vấn đề và áp dụng cho các bài tương tự Các bài tập có sự sosánh với cách lập trình của học sinh trước và khi áp dụng kỷ thuật “chặt nhị phân” từ đógiúp học sinh nắm rõ được tính cần thiết cũng như kỷ thuật để cài đặt thuật toán này
2.4.2 Đối với bản than và đồng nghiệp
Ban đầu gặp những dạng toán này, học sinh thường làm theo các cách thông thường,
áp dụng tìm kiếm tuần tự và một số cách tư duy giải toán khác nên không chạy được hết các
bộ test theo yêu cầu của đề bài, thường gặp lỗi chạy quá thời gian (Time limit) Sau một thờigian hướng dẫn học sinh cách tư duy, áp dụng kỷ thuật chặt nhị phân, học sinh đã có thể giảiquyết hầu hết các bài toán có sử dụng kỷ thuật này
Đề tài này có thể làm tài liệu cho học sinh và giáo viên trong quá trình giảng dạy
2.4.3 Đối với nhà trường
Đề tài đã và đang được áp dụng trong hoạt động giảng dạy nhằm nâng cao chất lượnggiảng dạy môn Tin học