1. Trang chủ
  2. » Tất cả

Ứ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

20 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

Thông tin cơ bản

Định dạng
Số trang 20
Dung lượng 218,91 KB

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

Nội dung

Ứ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 SỞ 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Á[.]

Trang 1

SỞ 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 2

MỤ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 3

1 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ương phá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áo khoa 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ác bà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ải như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ÁN TÌ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 4

2 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ăng dầ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 vi tì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 trong dã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 5

Khi 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ết vậ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 đó

Giới hạn:

1 ≤ N ≤ 105

1 ≤ A [i] ≤ 109

1 ≤ Q ≤ 105

1 ≤ M ≤ 105

Slbehon.inp Slbehon.out 5

1 4 10 5 6 4

2 3 5 11

1 1 2 5

Trang 6

Cá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ến lưu giá trị đếm Chương trình được viết như sau:

function dem(m:longint):longint;

var i:longint;

begin

dem:=0;

for i:=1 to n do

if a[i]<m then inc(dem);

end;

for i:=1 to n do read(f,a[i]);

readln(f);

readln(f,q);

for i:=1 to q do

begin

readln(f,x);

writeln(f1,dem(x));

end;

end;

Với cách giải trên ta có: Hàm Dem có độ phức tạp O(N) và bài toán có Q test nên độ phức tạp là Q.O(N) Với yêu cầu 1 ≤ N ≤ 105; 1 ≤ Q ≤ 105 thì cách giải trên không thực hiện hết được các test lớn có Q, N tối đa

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 7

var a:array[1 nmax] of longint;

n,m,q:longint;

f,f1:text;

procedure qsort(l,h:integer);

var i,j,tam,k:longint;

begin

i:=l;

j:=h;

k:=a[(l+h) div 2];

repeat

while a[i]<k do inc(i);

while a[j]>k do dec(j);

if i<=j then

begin

tam:=a[i];

a[i]:=a[j];

a[j]:=tam;

inc(i);

dec(j);

end;

until i>j;

if i<h then qsort(i,h);

if j>l then qsort(l,j);

end;

function tknp(x:longint):longint;

var d,c,giua,res:longint;

begin

res:=-1;

d:=1;

c:=n;

while d<=c do

Trang 8

begin

giua:=(d+c)div 2;

if a[giua]>=x then c:=giua-1

else

if a[giua]<x then

begin

res:=giua;

d:=giua+1;

end;

end;

if res=-1 then tknp:=0

else tknp:=res;

end;

procedure doc;

var i:integer;

x:longint;

begin

assign(f1,fo);

rewrite(f1);

assign(f,fi);

reset(f);

readln(f,n);

for i:=1 to n do read(f,a[i]);

qsort(1,n);

readln(f);

readln(f,q);

for i:=1 to q do

begin

readln(f,x);

writeln(f1,tknp(x));

end;

Trang 9

begin

doc;

close(f1);

end

Bài 2 Cho 1 dãy N số khác nhau Hãy tìm xem có bao nhiêu cặp số có chênh lệch là k

đơn vị

Dữ 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’

- Gồm một số duy nhất là số cặp có độ chênh lệch k

Capso.inp Capso.out Giải thích test

6 2

1 3 2 4 9 5

3 3 cặp số đó là; (1,3) (3,5) và (2,4)

Cách 1: Sử dụng 2 vòng For để duyệt và tìm ra 1 cặp số chênh lệch k đơn vị thì tăng biến đếm

begin

doc;

dem:=0;

for i:=1 to n-1 do

for j:=i+1 to n do

if abs(a[i]-a[j])=k then inc(dem);

assign(f,fo);

Trang 10

rewrite(f);

writeln(f,dem);

close(f);

end

Chương trình trên có độ phức tạp là O(N2) Với giới hạn input của bài toán là (N≤105) thì chương trình trên không thực hiện được với test tối đa

Cách 2: Sử dụng kỷ thuật “chặt nhị phân” Đầu tiên ta sắp xếp dãy tăng dần bằng Qsort Tiếp theo ta duyệt dãy A Tại Ai, nếu hàm TKNP(A[i]-k)=true thì ta tăng biến đếm (tìm được 1 số có chênh lệch k so với A[i]) Độ phức tạp O(NlogN)

program capso;

const fi='capso.inp';

fo='capso.out';

nmax=100000;

var f:text;

n,k,dem:longint;

a:array[1 nmax] of longint;

procedure doc;

var i:longint;

begin

assign(f,fi);

reset(f);

readln(f,n,k);

Trang 11

for i:=1 to n do read(f,a[i]);

end;

procedure sort(l,h:longint);

var

i,j,tam,x:longint;

begin

i:=l;

j:=h;

x:=a[(l+h) div 2];

repeat

while a[i]<x do inc(i);

while x<a[j] do dec(j);

if i<=j then

begin

tam:=a[i];

a[i]:=a[j];

a[j]:=tam;

inc(i);

dec(j);

end;

until i>j;

Trang 12

if l<j then sort(l,j);

if i<h then sort(i,h);

end;

function tknp(i:longint):boolean;

var d,c,g:longint;

begin

d:=1;

c:=n;

while d<=c do

begin

g:=(d+c) div 2;

if (a[g]=i) then

begin

exit(true);

end;

if a[g]<i then d:=g+1

else c:=g-1;

end;

exit(false);

end;

Trang 13

procedure xuli;

var i:longint;

begin

sort(1,n);

for i:=1 to n do

if (tknp(a[i]-k)) then inc(dem);

end;

begin

doc;

dem:=0;

xuli;

assign(f,fo);

rewrite(f);

write(f,dem);

close(f);

end

Bà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 14

In 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ố

Quanbai.inp Quanbai.out

5 21

5 6 7 8 9

21

Cách 1: Duyệt 3 vòng For và tìm max Độ phức tạp O(n3)

program quanbai;

const fi='quanbai.inp';

fo='quanbai.out';

var f:text;

n,m,max:longint;

a:array[1 100] of longint;

procedure doc;

var i:longint;

begin

assign(f,fi);

reset(f);

readln(f,n,m);

for i:=1 to n do read(f,a[i]);

end;

Trang 15

procedure xuly;

var i,j,z:longint;

begin

for i:=1 to n-2 do

for j:=i+1 to n-1 do

for z:=j+1 to n do

if (a[i]+a[j]+a[z]>max) and (a[i]+a[j]+a[z]<=m) then max:=a[i]+a[j]+a[z];

end;

begin

doc;

max:=0;

xuly;

assign(f,fo);

rewrite(f);

writeln(f,max);

close(f);

end

Cách 2: Sử dụng thuật toán chặt nhị phân Gọi a[z] là số lớn nhất trong bộ 3 số a[i], a[j], a[z] Tìm kiếm nhị phân số a[z] sao cho tổng 3 số <=M Lưu ý cần sắp xếp mảng A trước khi tìm kiếm Độ phức tạp O(N2logN)

Trang 16

program quanbai;

const fi='quanbai.inp';

fo='quanbai.out';

var f:text;

n,m,max:longint;

a:array[1 100] of longint;

procedure doc;

var i:longint;

begin

assign(f,fi);

reset(f);

readln(f,n,m);

for i:=1 to n do read(f,a[i]);

end;

function tknp(i,j:longint):longint;

var d,c,g,s:longint;

begin

tknp:=0;

d:=j+1;

c:=n;

while d<=c do

Trang 17

begin

g:=(d+c) div 2;

s:=a[i]+a[j]+a[g];

if s>m then c:=g-1

else

if s=m then

begin

tknp:=a[g];

exit;

end

else

begin

tknp:=a[g];

d:=g+1;

end;

end;

end;

procedure qsort(l,h:integer);

var i,j,tam,k:longint;

begin

i:=l;

j:=h;

Trang 18

k:=a[(l+h) div 2];

repeat

while a[i]<k do inc(i);

while a[j]>k do dec(j);

if i<=j then

begin

tam:=a[i];

a[i]:=a[j];

a[j]:=tam;

inc(i);

dec(j);

end;

until i>j;

if i<h then qsort(i,h);

if j>l then qsort(l,j);

end;

procedure xuly;

var i,j,z:longint;

begin

for i:=1 to n-2 do

for j:=i+1 to n-1 do

Trang 19

begin

z:=tknp(i,j);

if z=0 then break

else

if (a[i]+a[j]+z>max) and (a[i]+a[j]+z<=m) then

max:=a[i]+a[j]+z;

end;

end;

begin

doc;

qsort(1,n);

max:=0;

xuly;

assign(f,fo);

rewrite(f);

writeln(f,max);

close(f);

end

Bà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)

Trang 20

- Dòng tiếp theo cho biết số kẹo trong hộp thứ i

- 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

Kết quả: Tệp ‘Thutukeo.out’:

- Chứa Q dòng In ra hộp kẹo tương ứng với thứ tự viên kẹo, mỗi kết quả trên 1 dòng

‘Thutukeo.inp’ ‘Thutukeo.out’ Ghi chú

2

2 3

2

2

4

1 2

Hộp đầu tiên sẽ có các viên kẹo thứ tự: 1, 2 Hộ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ực hiện tìm kiếm nhị phân trên mảng S

program chiso_keo;

const nmax=100000;

fi='thutukeo.inp';

fo='thutukeo.out';

var a:array[1 nmax] of longint;

n,q,x:longint;

s:array[0 nmax] of int64;

f,f1:text;

function tknp(x:longint):longint;

var d,c,k:longint;

begin

d:=1;

c:=n;

while d<=c do

Ngày đăng: 01/11/2022, 19:33

TỪ KHÓA LIÊN QUAN

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

w