Thuật toán tìm kiếm nhị phân
Trang 1Tìm Kiếm Nhị Phân
Vũ Anh Quân
Thuật toán tìm nhị phân hay còn gọi là phương pháp chia đôi được ápdụng rất nhiều trong tin học Phương pháp này làm giảm được nhiều thời gian tìmkiếm, giúp chương trình chạy nhanh hơn Sau đây tôi xin giới thiệu một số bàitoán sử dụng phương pháp trên
Bàitoán 1: Xác định vị trí của phần tử X trong bảng liệt kê sắpxếp tăng các phần tử phân
biệt A1, A2, , AN.(A1< A2< < AN)
Bài giải: Chia đôi bảng liệt kê A1, A2, , AN thành 2 bảng liệt kê:
A1, A2, , Am và Am+1,Am+2, , AN (trong đó m=(N+1) div 2)
+Nếu X>Am thìtìm kiếm trên bảng liệt kê Am+1, Am+2, , AN
+Nếu X<=Am thìtìm kiếm trên bảng liệt kê A1, A2, , Am
Quá trình trên được thực hiện cho tới khi bảng liệt kêchỉ còn một phần tử Sau đó so sánh
X với số hạng này
Mô tả thuật toán tìm kiếm nhị phân
Function VT(X: integer): integer ;
Var
i, j, m : integer;
Begin
i:=1; j:=N;
while i<>
begin
m:= (i+j) div 2;
if X>A[m] then i:=m+1 else i:=m;
end;
Trang 2if x=A[i] then VT:=i else VT:=0;
End;
Bài toán 2:
Có N thành phố, cho biết mỗi con đường nối từ thành phố bất kìi đến thành phố bất kì j (với i khác j) có thể cho xe với trọng tải không quáC[i,j] đi qua Cho thành phố xuất phát
x và thành phố đích y Hãy tìm một đườngđi từ thành phố x tới thành phố y mà trọng tải lớn nhất có thể được
Dữ liệu vàotrong file Thanhpho.inp có dạng
Dòng đầu gồm 3 số N,x,y (N ≤ 100)
N dòng sau mỗi dòng N số nguyên không âm thể hiện matrận C[i,j]
(C[i,j]kiểu Integer)
Kết quả ra file Thanhpho.out có dạng
- Dòng đầu làtrọng tải lớn nhất có thể đi được từ x tới y
- Dòng hai làdãy các thành phố từ x tới y
Ví dụ:
4 1 4
0 2 1 1
1 0 2 1
1 1 0 2
1 1 1 2
2
1 2 3 4
Bài giải:
Cmax =MAX{Cij} với mọi i khác j; Cmin =0;
Kết quả bài toán sẽ nằm trong đoạn [ Cmin , Cmax]
Đặt Ctg = (Cmax+Cmin)div 2
Trang 3Ta sẽ thử xem xe có trọng tải Ctg có thể tồntại đường đi từ x tới y hay không? Dùng thuật toán tìm kiếm theo chiều sâu(hoặc tìm kiếm theo chiều rộng) để xác định đường đi từ x tới y Chú ý rằng nếuCtg ≤ C[i,j] thì có thể đi được từ thành phố i sang thành phố j
Nếu tồn tại đường đi ta sẽ tìm kiếm tiếp trong đoạn [Ctg +1,Cmax ],và lưu kết quả này Nếu không tồn tại đường đi ta sẽ tìm kiếm tiếp trongđoạn [Cmin ,Ctg -1]
Cứ tiếp tục tìm kiếm cho tới khi đoạn có điểm đầu lớnhơn điểm cuối
Chương trình thể hiện thuật toán trên như sau:
{$A+, B-, D+, E+, F-, G-, I+, L+, N-, O-, P-, Q+, R+,S+, T-, V+, X+}
{$M 16384, 0, 655360}
uses crt;
const
max = 100;
fi = 'thanhpho.inp';
fo = 'thanhpho.out';
var
c : array[1 max,1 max] of integer;
dx,kq, lkq : array[1 max] ofinteger;
cmin, cmax, ctg, ckq: word;
n, x, y, dem, ldem : integer;
ok : boolean;
procedure docf;
var
f : text;
i, j : integer;
Trang 4cmin:= 0; cmax:= 0;
assign(f,fi);
reset(f);
readln(f,n,x,y);
for i:=1 to n do
for j:=1 to n do
begin
read (f, c[i,j]);
if c[i,j]>cmax then cmax:=c[i,j]; end;
close(f);
end;
procedure ghinhan;
begin
ckq:= ctg;
ldem:= dem;
lkq:= kq;
ok:= true;
end;
procedure di(i: integer);
var
j: integer;
Trang 5if ok then exit;
for j:=1 to n do
if (dx[j]=0) and (c[i,j]>=ctg) then begin
dx[j]:=1;
inc(dem);
kq[dem]:=j;
if j=y then ghinhan
else di(j);
if ok then exit;
dec(dem);
end;
end;
procedure lam;
begin
while cmin<=cmax do
begin
ctg:= (cmin+cmax) div 2;
fillchar(dx,sizeof(dx),0);
dem:=1; kq[1]:=x;
ok:= false;
di(x);
Trang 6if ok then cmin:= ctg+1
else cmin:= ctg-1;
end;
end;
procedure ghif;
var
f : text;
k : integer;
begin
assign(f,fo);
rewrite(f);
writeln(f,ckq);
for k:=1 to ldem do write(f,lkq[k],#32);
close(f);
end;
BEGIN
docf;
lam;
ghif;
END
Bài toán 3: Biết rằng căn bậc N của một số S là một sốnguyên <106 Tìm căn bậc N của
S
Dữ liệu vào trong file CANBACN.INP có dạng
Dòng 1 là số N (N ≤ 100)
Trang 7Dòng 2 là số S(0 ≤ S ≤ 10100 )
Kết quả ra file CANBACN.OUT có dạng
Gồm 1 dòng duy nhất là căn bậc N của số S
Ví dụ:
CANBACN.INP CANBACN.OUT
4
Bài giải: Cmin =0; Cmax = 106.Kết quả sẽ nằm trong đoạn [Cmin ,Cmax ]
Đặt Ctg =(Cmin +Cmax )div 2 Tính A= CTGN Để tính A ta dùng thuật toán nhân sốlớn Nếu A > S thì tìm kiếm trong đoạn [Ctg+1 ,Cmax ]
Nếu A < S thì tìm kiếm trong đoạn [ Cmin , C tg -1 ]
Nếu A=S thì căn bậc N của S chính là Ctg
Tiếp tục tìm kiếm cho tới khi Cmin >Cmax
Chương trình thể hiện thuật toán
{$A+, B-, D+, E+, F-, G-, I+, L+, N-, O-, P-, Q+, R+,S+, T-, V+, X+}
{$M 16384, 0, 655360}
uses crt;
const
max:= 100;
fi:= 'canbacn.inp';
fo: = 'canbacn.out';
var
s : string;
Trang 8n : integer;
cmin, cmax, ctg: longint;
procedure docf;
var
f : text;
begin
assign(f,fi);
reset(f);
readln(f,n);
readln(f,s);
close(f);
end;
function nhan(x:string; so: longint): string; var
nho, tich : longint;
k : integer;
y : string;
begin
y:=''; nho:=0;
for k:=length(x) downto 1 do
begin
tich:= so*(ord(x[k])-48)+nho;
y:= chr(tich mod 10+48)+y;
Trang 9nho:= tich div 10;
end;
while nho>0 do
begin
y:= chr(nho mod 10+48) + y;
nho:= nho div 10;
end;
nhan:= y;
end;
function kiemtra: integer;
var
kq : string;
k : integer;
begin
kq:= '1';
for k:=1 to n do kq:= nhan(kq,ctg);
if length(kq)=length(s) then
begin
if kq=s then kiemtra:=0
else if kq>s then kiemtra:=1
else kiemtra:=2;
end;
else if length(kq)>length(s) then kiemtra:=1
Trang 10end;
procedure lam;
var
kt : integer;
begin
cmin:= 0;
cmax:= 1000000;
while cmin<=cmax do begin
ctg:= (cmin+cmax)div 2; kt:= kiemtra;
case kt of
0 : exit;
1 : cmax:= ctg-1;
2 : cmin:= ctg+1;
end;
end;
end;
procedure ghif;
var
f : text;
begin
Trang 11rewrite(f);
write(f,ctg);
close(f);
end;
BEGIN
docf;
lam;
ghif;
END
Bài tập tự giải:: Dây chuyền sản xuất.
Một dây chuyền sản xuất có N (N ≤ 100) vị trí Có Ncông nhân, cho biết năng suất của công nhân thứ i mà làm ở vị trí thứ j là Cij (Cij : Integer) Hãy sắpxếp N công nhân vào N
vị trí sao cho năng suất cao nhất có thể được