Tải bản đầy đủ (.doc) (14 trang)

BÀI TOÁN XÂU TRONG CỰC ĐẠI VÀ LỜI GIẢI

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (494.95 KB, 14 trang )

1. BÀI TOÁN XÂU TRONG CỰC ĐẠI
Xâu con:
S là xâu con của T nếu S nhận được bằng cách xoá đi một số ký tự nào đó trong T.
Ví dụ: ‘EAC’ là xâu con của ‘CEAEEC’
Xâu con chung:
Nếu xóa một số ký tự của hai xâu thì hai xâu con còn lại của chúng bằng nhau
Ví dụ: S1=‘ABCDAE’ và S2=‘XYACADK’ có xâu ‘ACD’ là xâu con chung có độ
dài cực đại.
Bài toán đặt ra:
Cho 2 xâu A, B. Tìm một xâu S là xâu con chung của A và B có độ dài cực đại.
- Input: File Input.doc có cấu trúc:
+ Dòng thứ nhất chứa xâu A
+ Dòng thứ hai chứa xâu B
- Output: File output.doc có cấu trúc:
Nếu bài toán vô nghiệm thì ghi số 0, ngược lại ghi như sau:
+ Dòng thứ nhất ghi số K là số kí tự của xâu chung S
+ Dòng thứ hai là xâu S gồm K kí tự.
BÀI GIẢI:
B1: Phân tích bài toán
Gọi M= length(A); N= length(B);
* Cần xây dựng mảng L[0 M, 0 N] với ý nghĩa: L[I,j] là độ dài của xâu chung dài
nhất của 2 xâu: A[0 i] và B[0 j].
* Bài toán ban đầu là: L[M,N].
Đương nhiên nếu một xâu là rỗng (số kí tự là 0) thì xâu con chung cũng là rỗng, vì
vậy:
L[0,j]=0 ∀ j, j=1 N.
L[i,0]=0 ∀ i, i=1 M.
B2: Giải pháp đệ quy
Với M ≥ I > 0 và N ≥ j > 0 thì:
+ Nếu A[i]=B[j] thì L[I,j] = L[i-1,j-1] +1
+ Nếu A[i] < > B[j] thì:


* Nếu A[i] trong B[1 j] thì nó chỉ thuộc B[1 j-1] nên L[I,j]=L[I,j-1]
* Nếu B[j] trong A[1 i] thì nó chỉ thuộc A[1 i-1] nên L[I,j]=L[I-1,j]
Vì vậy: L[I,j] được tính theo công thức truy hồi sau:
L[I,j] = Max{L[I,j-1], L[i-1,j], L[i-1,j-1] + X} (với X=0 nếu A[i] < > B[j]; X=1 nếu
A[i] = B[j]).
B3: Lập bảng
PROCEDURE LAPBANG;
VAR I,J: BYTE;
BEGIN
FOR I:=1 TO M DO L[I,0]:=0;
FOR J:=1 TO N DO L[0,J]:=0;

FOR I:=1 TO M DO
FOR J:=1 TO N DO
BEGIN
IF A[I] = B[J] THEN L[I,J]:= L[I-1,J-1] +1
ELSE
L[I,J]:=MAX(L[I,J-1],L[I-1,J]);
END;
END;
B4: Tổng hợp kết quả
Procedure TongHop;
Begin
S:=’’;
While (i>0) and (j>0) Do
If L[i,j]=L[i,j-1] then j:=j-1
Else
If L[i,j]=L[i-1,j] then i:=i-1
Else
Begin

S:=A[i]+S;
i:=i-1;
j:=j-1;
End;
End;
* CÀI ĐẶT:
USES CRT;
CONST FI='INPUT.DOC'; FO='OUTPUT.DOC';
VAR F: TEXT; M,N: BYTE; A,B,S: STRING; CH:CHAR;
L: ARRAY[0 100,0 100] OF BYTE;
PROCEDURE DOC_INPUT;
VAR F: TEXT;
BEGIN
M:=0; N:=0;A:=''; B:='';
ASSIGN(F,FI); RESET(F);
WHILE NOT EOLN(F) DO
BEGIN
INC(M); READ(F,CH); A:=A+CH;
END;
READLN(F);
WHILE NOT EOLN(F) DO
BEGIN
INC(N); READ(F,CH); B:=B+CH;
END;
CLOSE(F);
END;
FUNCTION MAX(I,J: INTEGER) : INTEGER;
VAR P: INTEGER;
BEGIN
IF I>J THEN MAX:=I ELSE MAX:=J;

END;
PROCEDURE LAPBANG;
VAR I,J: BYTE;
BEGIN
FOR I:=1 TO M DO L[I,0]:=0;
FOR J:=1 TO N DO L[0,J]:=0;
FOR I:=1 TO M DO
FOR J:=1 TO N DO
BEGIN
IF A[I] = B[J] THEN L[I,J]:= L[I-1,J-1] +1
ELSE
L[I,J]:=MAX(L[I,J-1],L[I-1,J]);
END;
END;
PROCEDURE TONGHOP;
VAR F: TEXT; I,J: INTEGER;
BEGIN
ASSIGN(F,FO); REWRITE(F);
IF L[M,N]= 0 THEN
BEGIN
WRITE(F,0); CLOSE(F);HALT;
END
ELSE
BEGIN
WRITELN(F,L[M,N]);
I:=M; J:=N;
S:='';
WHILE (I>0) AND (J>0) DO
IF L[I,J] = L[I,J-1] THEN DEC(J)
ELSE

IF L[I,J]=L[I-1,J] THEN DEC(I)
ELSE
BEGIN
S:=A[I]+S;
DEC(I); DEC(J);
END;
END;
WRITE(F,S);
CLOSE(F);
END;
BEGIN
CLRSCR;
DOC_INPUT; LAPBANG; TONGHOP;
END.
2. BÀI TOÁN DU LỊCH
* Phát biểu bài toán:
Một người đi từ thành phố 0 đến thành phố n và có thể đi qua n-1 thành phố
khác 1, 2, . . ., n-1, theo lộ trình: 0 -> i
1
-> i
2
. . . -> i
k
-> n, trong đó: 0 < i
1
< i
2
<
i
k

< n. Giá vé xe đi từ thành phố i đến thành phố j là c[i,j].
Tìm một lộ trình từ thành phố 0 đến thành phố n sao cho tổng chi phí về giá vé
đạt cực tiểu.
*Bước 1: Phân tích bài toán
- Gọi ρ(s) là bài toán du lịch, với:
(thành phố xuất phát là 0)
s Î N: là thành phố cần đến.
( Bài toán ban đầu là ρ(n))
- Các giá trị cần tìm:
l[s]: chi phí nhỏ nhất để đi từ 0

s của bài toán ρ(s)
u[s]: đỉnh kế cuối trên đường đi từ 0

s của bài toán ρ(s)
* Bước 2: Giải pháp đệ quy
- Nếu s=0 thì:
• l[0] = 0
• u[0] = -1
- Nếu s≠0 (0<s) thì:
• l[s] = min (l[k] + c[k,s])
(0

k<s)
= l[k’] + c[k’,s]

• u[s] = k’
* Bước 3: Lập bảng
Procedure Lapbang;
Begin

for s:= 0 to n do
if (s= 0) then Tính l[0] và u[0]
else Tính l[s] và u[s]
End;
Cụ thể:
Procedure lapbang;
var s,k,ke: byte;
min,tam: integer;
begin
for s:=0 to n do
if (s=0) then
begin
l[0]:=0;
u[0]:=-1;
end
else
begin
ke:=0;
min:=max;
for k:=r to s-1 do
if (c[k,s]>0) then
begin
tam:=l[k]+c[k,s];
if (tam<min) then
begin
ke:=k;
min:=tam;
end;
end;
l[s]:=min;

u[s]:=ke;
end;
end;
 Độ phức tạp tính toán: O(n
2
)
* Bước 4: Tổng hợp kết quả
Procedure Tonghop;
Begin
i :=1; s := n; x[1] := s;
while s ≠ 0 do
begin
i := i + 1;
s := u[s];
x[i]:= s;
end;
End;
* Chương trình:
const max=32767;
var c:array[0 100,0 100] of integer;
u,l, x:array[1 100] of integer;
n:byte;
procedure docfile;
var f:text;
i,j:byte;
begin
assign(f,'input.txt');reset(f);
readln(f,n);
for i:=0 to n do
for j:=0 to n do read(f,c[i,j]);

close(f);
end;
procedure lapbang;
var s,k,ke:byte;
min,tam:integer;
begin
for s:=0 to n do
if (s=0) then
begin
l[0]:=0;
u[0]:=-1;
end
else
begin
ke:=0;
min:=max;
for k:=0 to s-1 do
if (c[k,s]>0) then
begin
tam:=l[k]+c[k,s];
if (tam<min) then
begin
ke:=k;
min:=tam;
end;
end;
l[s]:=min;
u[s]:=ke;
end;
end;

procedure tonghop;
var i,s,dem:byte;
begin
s:=n;
x[1]:=s;
i:=2;
while (s<>0) do
begin
x[i]:=u[s];
s:=x[i];
i:=i+1;
end;
if (s<>0) then write('Khong co duong di')
else
begin
write('Duong di voi chi phi nho nhat: ');
for dem:=i-1 downto 1 do write(' ',x[dem]:2);
writeln;
writeln('Chi phi nho nhat: ',l[n]);
end;
end;
BEGIN
docfile;
lapbang;
tonghop;
readln;
END.
3. BÀI TOÁN SINH VIÊN ÔN THI
a. Phát biểu bài toán
Một sinh viên còn m ngày để ôn thi n môn. Theo kinh nghiệm của anh ta,

nếu ôn môn j trong i ngày thì được điểm là a[i,j]. Giả sử cho biết các a[i,j] (với
a[i,j] ≤ a[i+1,j]).
Tìm bộ x[j] (số ngày ôn môn j, j = 1 n) sao cho Σx[j] = m và sinh viên đạt
tổng điểm lớn nhất. (Σa[x[j], j] → max).
 Input:
- m ∈ N: số ngày ôn thi
- n ∈ N* : số môn ôn thi
- a[i,j] ∈ R: điểm đạt được khi ôn thi môn j trong i ngày. (i=0 m, j=1 n)
 Output:
x[j]: số ngày ôn thi môn j (j=1 n) sao cho Σx[j]=n và Σa[x[j],j] đạt max
b. Phân tích bài toán
Gọi P(r,s) là bài toán ôn thi, với:
• r ∈N là số ngày ôn thi.
• s ∈ N* là số môn ôn thi.
(Bài toán ban đầu là P(m,n))
Các giá trị cần tìm:
• diem[r,s]: tổng điểm lớn nhất Σa[x[j],j] của bài toán P(r,s).
• ngay[r,s]: số ngày ôn thi môn s (tức là x[s]) của bài toán P(r,s).
c. Giải pháp đệ quy
• Trường hợp suy biến: s=1 (chỉ có 1 môn)
- ngay[r,s]=ngay[r,1]=r (vì chỉ có 1 môn nên tận dụng hết tất cả r ngày để
ôn thi)
- diem[r,s]=diem[r,1]=a[r,1]
• Trường hợp đệ quy (s>1):
- diem[r,s] = max (a[k,s]+diem[r-k,s-1]) (k: số ngày ôn, 0≤k≤ r thi môn
s)
= a[k’,s]+diem[r-k’,s-1]
Trong đó:
 a[k,s] là điểm thi môn thứ s với k ngày ôn
 diem[r-k,s-1] là tổng điểm tối ưu của s-1 môn thi với r-k ngày ôn

 k' là số ngày ôn thi môn s mà tại đó diem[r,s] có giá trị tối ưu
- ngay[r,s] = k’
d. Lập bảng
Thủ tục LapBang như sau:
Procedure LapBang;
Begin
For r:=0 to m do
For s:=1 to n do
If s=1 then
begin
diem[r,s]:=a[r,s];
ngay[r,s]:=r;
end
Else Tinhdiem_ngay; {Tinh diem[r,s] và ngay[r,s]}
End;
Độ phức tạp tính toán: O(n.m
2
)
Trong đó:
Procedure Tinhdiem_ngay;
Var tam, k,k1:integer;
Begin
k1:=0;
tam:=a[0,s]+diem[r,s-1];
For k:=1 to r do
if tam<a[k,s]+diem[r-k,s-1] then
begin
tam:=a[k,s]+diem[r-k,s-1];
k1:=k;
end;

diem[r,s]:=tam;
ngay[r,s]:=k1;
End;
e. Tổng hợp kết quả
Procedure TongHop;
Begin
r:=m;
For s:=n downto 1 do
begin
x[s]:=ngay[r,s];
r:=r-x[s];
end;
End;
• Độ phức tạp tính toán: O(n)
f. Cài đặt chương trình (bằng Turbo Pascal)
Program Sinh_vien_on_thi;
Uses crt;
Type Mang=array[1 50,1 50] of integer;
Var i,j,r,s,k,n,m,tam,k1:Integer;
A,ngay,diem:Mang;
X:Array[1 2500] of integer;
f:Text;
ch:Char;
{Tao file Input.txt de luu du lieu}
Procedure NhapDL;
Begin
Assign(f,'Input.txt');
Rewrite(f);
Write('Nhap so ngay on thi: ');
Readln(m);

Writeln(f,m);
Write('Nhap so mon on thi: ');
Readln(n);
Writeln(f,n);
For i:=0 to m do
begin
For j:=1 to n do
begin
Write('Nhap diem a[',i,',',j,']= ');
Readln(a[i,j]);
Write(f,a[i,j]:5,' ');
end;
Writeln(f);
end;
Close(f);
End;
{Doc du lieu tu file Input.txt luu vao bien m,n va mang A}
Procedure DocDL;
Begin
Assign(f,'Input.txt');
Reset(f);
Readln(f,m);
Readln(f,n);
For i:=0 to m do
begin
For j:=1 to n do
Read(f,a[i,j]);
Readln(f);
end;
Close(f);

End;
{Buoc lap bang}
Procedure Lap_bang;
Begin
DocDL;
For r:=0 to m do
begin
For s:=1 to n do
begin
If s=1 then
begin
ngay[r,1]:=r;
diem[r,1]:=A[r,1];
end
Else
begin
tam:=a[0,s]+diem[r,s-1];
k1:=0; {k1 la k'}
For k:=1 to r do
If tam<a[k,s]+diem[r-k,s-1] then
begin
tam:=a[k,s]+diem[r-k,s-1];
k1:=k;
end;
diem[r,s]:=tam;
ngay[r,s]:=k1;
end;
Write(diem[r,s]:5,'/',ngay[r,s],' ');
end;
Writeln;

end;
End;
{Buoc tong hop ket qua}
Procedure Tong_hop;
Begin
r:=m;
For s:=n downto 1 do
Begin
X[s]:=ngay[r,s];
Writeln('So ngay on thi mon ',s,' tot nhat la: ',X[s]);
r:=r-X[s];
End;
End;
{In du lieu vua doc ra tu file Input.txt}
Procedure HienthiDL;
Begin
DocDL;
Writeln('So ngay on thi: ',m);
Writeln('So mon on thi: ',n);
Writeln('So diem: ');
For i:=0 to m do
begin
For j:=1 to n do
Write(a[i,j]:5);
Writeln;
end;
End;
BEGIN
Clrscr;
Write('Ban co muon tao moi du lieu khong? (c/k) ');

Readln(ch);
If upcase(ch)<>'K' then
NhapDL;
Writeln;
Writeln('* DU LIEU VAO: ');
HienthiDL;
Readln;
Writeln('* LAP BANG');
Lap_bang;
Writeln;
Writeln('* KET QUA: ');
Tong_hop;
Write('Tong diem: ',diem[m,n]);
Readln;
END.

×