Professional Documents
Culture Documents
Đỗ Quốc Trí
Như ta đã biết quy hoạch động là một phương pháp phổ biến để giải các bài toán, và nếu
bạn đã học lập trình thì không thể không biết đến phương pháp này. Trong bài viết tôi
muốn đề cập đến phương pháp này với bài toán nhân ma trận đơn giản tiến tới áp dụng
giải các bài toán thực tế phức tạp hơn
Cho ma trận A có kích thước p*q và ma trận B có kích thước q*r thực hiện phép nhân ma
trận để có ma trận C có kích thước p*r
C[i,j] = ồ A[i,k]*B[k,j] (k : 1 ->q ; 1 <= i <= p , 1 <= j <= q)
Vi dụ:
A*B=C
Ma trận A có kích thước 3*4, Ma trận B có kích thước 4*5, Ma trận C có kích thước 5*3.
Để nhân ma trận ta Ăp*q) voi B (q*r) ta thực hiện chương trình sau
For i := 1 to p do
For j := 1 to r do
Begin
C[i,j] := 0 ;
For k := 1 to q do C[i,j] := C[i,j] + A[i,k] * A[k,j] ;
end ;
Dễ dàng thấy để nhân 2 ma trận này với nhau ta cần phải dùng p *q* r phép nhân, ta gọi
đây là phí tổn để nhân 2 ma trận này.
Vấn đề đặt ra là nhân một dãy ma trận M1 , M2 , M3 …Mn ;
Ta chú ý là phép nhân ma trận khôngcó tính chất giao hoán nhưng có tính chất kết hơp.
Ví dụ (A* B)*C = A*(B*C) ;
Dữ liệu vào File MATRAN.INP
Dòng đầu ghi n
Dòng thứ 2 ghi n+1 so a[1]...a[n+1] với ý nghĩa kích thước của ma trận M[i] là
a[i]*a[i+1]
Dữ liệu ra File MATRAN.OUT
Ghi số n là số phép nhân cần thực hiện.
Ví dụ:
Cho mảng gồm 3 phần tử a, b, c ta xác định phép toán nhân sau
chẳng hạn ta có aa = b ; ac = c ; chú ý ở đây không có tính kết hợp và giao hoán.
Bài toán đặt ra là cho 1 sâu có độ dài không quá 100, hãy tìm cách đặt dấu ngoặc để thể
hiện phép nhân sao cho kết quả là a.
Input GIATRI.INP: ghi sâu S
Output GIATRI.OUT nếu không đạt được thì ghi 0 nếu đạt được thì ghi cách đặt.
Ví dụ:
Procedure trace(i,j : byte; c : char) ; {dùng đệ quy để truy vết in kết quả }
var
k : byte ;
u , v : char ;
begin
if i = j then
begin
write(Fo,A[i]) ;
exit ;
end;
Write(Fo , ’(’) ;
k := F[i,j,c] ;
for u := ’a’ to ’c’ do
For v := ’a’ to ’c’ do
if (F[i,k,u] <> 0) and (F[k+1,j,v] <> 0) and (x[u,v] = c) then
begin
Trace(i,k,u) ; trace(k+1,j,v) ;
end;
Write(Fo , ’)’) ;
end;
{ Ch ương trình chính }
Begin
Enter ;
Init ;
Optimize ;
If F[1,n,’a’] = 0 then write(Fo , 0)
else Trace(1,n,’a’) ;
Close(Fo) ;
End.
Ta cũng có thể dùng chương trình đệ quy trên để ghi ra cách nhân trong bài nhân ma trận.
Từ các bài toán trên ta rút ra công thúc truy hồi cho các bài có dạng như trên:
F[i,j] := cấu hình tốt nhất (F[i,k] , F[k+1,j]) với i <= k < j.
Các bạn có thể tham khảo bài toán sau
Cho n quân bài đặt liền nhau, trên quân bài thứ i có ghi số A[i]. Nếu bạn rút quân bài k
thì bạn sẽ nhận số tiền là A[k-1] * A[k] *A[k+1] (1<k<n). Bài toán đặt ra là hãy rút n -2
sao cho số tiền nhận được là lớn nhất.
Input
Dòng 1: ghi số n
Dòng thứ 2: ghi n số, số thứ i là số ghi trên quân bài thứ i
Output
Ghi số tiền lớn nhất nhận được