Professional Documents
Culture Documents
Ôn Thi Cuối Kì
Ôn Thi Cuối Kì
Lý thuyết
Câu 1: Độ phức tạp thuật toán là gì? Ý nghĩa?
- Độ phức tạp thuật toán không phải là một đại lượng Toán học được nghiên cứu bài bản.
Trong Khoa học máy tính, đây được coi là công cụ để ước lượng độ lớn của hàm thời gian
cũng như so sánh tính hiệu quả giữa các giải thuật.
- Khi đề cập đến độ phức tạp thuật toán, người ta sử dụng các kí hiệu tiệm cận ( O, W, Q)
• Ý nghĩa:
+ Phân lớp cấp độ lớn của hàm thời gian (T(n)) khi n đủ lớn
+ Giải thuật nằm ở phân lớp thấp hơn thì hiệu quả hơn
Câu 2: Bậc tăng trưởng là gì? Ý nghĩa của bậc tăng trưởng?
- “Tốc độ tăng” của 1 hàm số không phải là một đại lượng tính toán được. Người ta chia
“tốc độ tăng” của hàm thành nhiều bậc từ bé đến lớn (tăng tuyến tính, tăng bậc 2, tăng phi
mã, …) và gọi chúng là “bậc tăng trưởng”.
- Bậc tăng trưởng được dựa trên những hàm phổ biến và đã biết trong Toán học. Ví dụ hàm
số 3n2 + 1 có bậc tăng trưởng là n2
• Ý nghĩa:
+ Phân lớp cấp độ lớn của hàm thời gian (T(n)) khi n đủ lớn
+ Hàm số có bậc tăng trưởng cao hơn thì sẽ tăng nhanh hơn và sẽ lớn hơn khi n đủ lớn
Câu 3: So sánh bậc tăng trưởng và độ phức tạp?
• Giống:
+ Đều là công cụ giúp ước lượng cấp độ lớn của hàm thời gian và so sánh giữa các hàm
thời gian hay giải thuật
+ Phân lớp cấp độ lớn của hàm thời gian (T(n)) khi n đủ lớn
• Khác:
+ Nói đến độ phức tạp là nói đến các kí hiệu tiệm cận (tức là nói về giới hạn trên, dưới)
Ví dụ, hàm số 3n2 + 1 có bậc tăng trưởng là n2, nhưng khi nói đến độ phức tạp, cách viết
( )
3n2 + 1 Î O n3 vẫn đúng vì n3 vẫn là một chặn trên của hàm số 3n2 + 1
II. Ký hiệu tiệm cận
Nhắc lại định nghĩa:
( )
f ( n) = O g ( n) Û $c Î + , n0 Î • : f ( n) £ cg ( n) , " ³ n0 (g(n) là chặn trên của f(n))
( )
f ( n) = W g ( n) Û $c Î + , n0 Î • : f ( n) ³ cg ( n) , " ³ n0 (g(n) là chặn dưới của f(n))
( )
f ( n) = Q g ( n) Û $c1 , c2 Î + , n0 Î • : c1g ( n) £ f ( n) £ c2 g ( n) , " ³ n0 (tiệm cận chặt chẽ)
Câu 1: Khẳng định bên dưới là đúng hay sai? Vì sao?
a, ( ) ( ( )) ( )
Nếu f n = Q g n , g n = Q h n thì h n = Q f n ( ( )) ( ) ( ( ))
( )
f ( n) = Q g ( n) Þ $c1 , c2 Î + , n1 Î • : c1g ( n) £ f ( n) £ c2 g ( n) , "n ³ n1 (1)
g ( n) = Q ( h ( n) ) Þ $c , c Î
3 4
+
, n2 Î • : c3 h ( n) £ g ( n) £ c4 h ( n) , "n ³ n2 (2)
1 1
Từ (1) ta suy ra f ( n) £ g ( n) £ f ( n) , "n ³ n1
c2 c1
1 1
Từ (2) ta suy ra g ( n) £ h ( n) £ g ( n) , "n ³ n2
c4 c3
ì 1 1 1
ïh ( n) £ c g ( n) £ c . c f ( n) , "n ³ n1 vaøn ³ n2
ï
Þí 3 3 1
ïh ( n) ³ 1 g ( n) ³ 1 . 1 f ( n) ,"n ³ n vaøn ³ n
ïî c4 c4 c2 1 2
1 1
Hay f ( n) £ h ( n ) £ f ( n) , "n ³ max {n1 , n2 }
c2 c4 c1c3
1 1
Chọn c5 = , c6 = , n = max {n1 , n2 } thì c5 f ( n) £ h( n) £ c6 f ( n) , "n ³ n0
c2 c4 c1c3 0
Theo định nghĩa Big- Q , ta suy ra h n Î Q f n ( ) ( ( ))
Vậy khẳng định ban đầu là đúng.
b, ( ) ( )
f ( n) = O g ( n) , g ( n ) = O h ( n ) Þ h ( n ) = W f ( n ) ( )
( )
f ( n) = O g ( n) Þ $c1 Î + , n1 Î • : f ( n) £ c1g ( n) , "n ³ n1 Û g ( n) ³
1
c1
h ( n) , "n ³ n1
( )
g ( n) = O h ( n) Þ $c2 Î + , n2 Î • : g ( n) £ c2 h ( n) , "n ³ n2 Û h ( n) ³
1
c2
g ( n) , "n ³ n2
1 1 1
Suy ra h ( n) ³ g ( n) ³ . f ( n) , "n ³ n1 vaøn ³ n2
c2 c2 c1
1
Chọn c = , n = max {n1 , n2 } Þ h ( n) ³ cf ( n) , "n ³ n0
c1c2 0
d, ( ) (
Q a g ( n) = Q g ( n) , "a > 0 )
(
ìQ a g ( n) Í Q g ( n)
ï
Ta sẽ chứng minh "a > 0 : í
) ( )
(
ïîQ g ( n) Í Q a g ( n) ) ( )
• Chứng minh "a > 0 : Q a g n Í Q g n ( ( )) ( ( ))
( )
Chọn hàm f n bất kì sao cho f ( n ) Î Q (a g ( n ) )
()
() ()
Chọn c3 = a c1 , c4 = a c2 Þ c3 g n £ f n £ c4 g n , "n ³ n0
Hay "f ( n) Î Q (a g ( n) ), ta có f ( n) Î Q ( g ( n) )
Suy ra Q (a g ( n) ) Í Q ( g ( n) ) (2)
Þ $c , c Î , n Î • : c g( n) £ f ( n) £ c g( n) , "n ³ n
1 2
+
0 1 2 0
(a g( n)) £ f ( n) £ a (a g( n)) , "n ³ n
c1 c2
Û
a 0
( ) ( )
c1 c2
Chọn c3 = , c4 = Þ c3 a g ( n) £ f ( n) £ c4 a g ( n) , "n ³ n0
a a
Theo định nghĩa Big- Q ta suy ra f ( n) Î Q a g ( n) ( )
( )
Hay "f ( n) Î Q g ( n) , ta có f ( n) Î Q a g ( n) ( )
( ( ))
Suy ra Q g n Í Q a g n ( ( )) (1)
(
Từ (1) và (2) ta suy ra Q a g ( n) = Q g ( n) , "a > 0 ) ( )
III. Sắp xếp theo thứ tự tăng dần của “order of growth”
Nhắc lại, tăng dần big-O theo thứ tự như sau:
c, log(n), n1/3, n1/2, …, n, n3/2, n2, n3, …, 2n, 3n, …, cn , n!, nn
Khi so sánh Big-O, log(n) = O(nc) trong đó c rất bé, nên nếu gặp O(n1/2) và O(n1/2+c) thì 2 cái xấp xỉ nhau
f1 ( n) = 22 f2 ( n) = 2100000 n f3 ( n) = Cn2 f4 ( n) = n n
1000000
Group 1:
f1 ( n) = 22 = O (1)
1000000
f2 ( n) = 2100000 n = O cn (c > 1) ( )
n ( n - 1)
f3 ( n) = Cn2 =
2
= O n2 ( )
f4 ( n) = n n = n3/ 2 = O n3/ 2 ( )
() ()
Vậy f1 n < f4 n < f3 n < f2 n () ()
f1 ( n) = n4Cn2 f2 ( n) = n ( log n) f3 ( n) = n5log n ;
4
Group 2:
n
f4 ( n) = 4 log n + log ( log n) f5 ( n) = å i
i =1
n ( n + 1)
f1 ( n) = n4 .
2
= O n6( )
f2 ( n) = n ( log n) = O n1/ 2 + 4 c ( )
4
f3 ( n) = n5log n = O nn ( ) c
() ()
Vậy f4 n < f2 n < f5 n < f1 n < f3 n () () ()
( ) f7 ( n) = nlog n f8 ( n) = 2n/2 f9 ( n) = 3 f10 ( n) = 4n
1/4
Group 3: f6 n = n n n
f 6 ( n) = 2
log n ( ) =2
n
n log n
=2
(
O nc+1/2 )
f7 ( n) = nlog n = 2
(
log nlog n ) = 2(log n)log n = 2O( n ) 2c
f 8 ( n ) = 2 n/ 2 = 2 ( )
On
f 9 ( n) = 3 n
=2
( ) =2
log 3 n
n log3
=2
( )
O n1/2
( )
1
f10 ( n) = 4 n = 22 n = 2
1/4 4 O n1/4
() ()
Vậy f7 n < f10 n < f9 n » f6 n < f8 n () () ()
( ) ( ) ()
Group 4: f1 n = n0.999999 log n ; f2 n = 10000000n; f3 n = 1.000001n; f4 n = n2 () ( )
f1 ( n) = n0.999999 log n = O n0.999999 + c ( )
f2 ( n) = 10000000n = O( n)
f3 ( n) = 1.000001n = O cn (c > 1) ( )
f4 ( n) = n2 = O n2 ( )
()
Vậy f1 n » f2 n < f4 n < f3 n () () ()
Group 5:
f1 ( n) = ( n - 2 )! f2 ( n) = 5log ( n + 100 ) f3 ( n) = 22 n
10
f4 ( n) = 0,001n4 + 3n3 + 1 f5 ( n) = ln2 n f6 ( n) = 3 n f7 ( n) = 3n
f1 ( n) = ( n - 2 )! = O( n!)
( )
f2 ( n) = 5log ( n + 100 ) = 50 log ( n + 100 ) = O nc (c > 0, c rất bé)
10
( )
f3 ( n ) = 2 2 n = 4 n = O 4 n
f4 ( n) = 0, 001n4 + 3n3 + 1 = O n4 ( )
( )
f5 ( n) = ln 2 n = O n2 c
1
æ 1ö
f6 ( n) = 3 n = n3 = O ç n3 ÷
ç ÷
è ø
( )
f 7 ( n ) = 3n = O 3n
() () () () ()
Vậy, f2 n » f5 n < f6 n < f4 n < f7 n < f3 n < f1 n () ()
IV. Lập và giải phương trình đệ quy
Câu 1: Lập phương trình đệ quy
a,
( )
Đặt T n là tổng chi phí khi thực hiện tính g(n)
() () (
Dễ thấy T 1 = c1.Với n > 1, ta có: g n = 3g n / 2 + g n / 2 + 5) ( )
Trong công thức trên, ta gọi đệ quy 2 lần hàm g với giá trị n/2
Þ T ( n) = 2T ( n / 2 ) + c2
ìïT (1) = c1
Phương trình đệ quy: í
ïîT ( n) = 2T ( n / 2 ) + c2 , n > 1
b,
Giải:
( ) ( )
Đặt T n là tổng chi phí khi gọi xn(n). Dễ thấy T 0 = c1
Với n > 0, hàm thực hiện gọi đệ quy cho các giá trị (n-i) với i chạy từ 1 đến n, tức là gọi đệ
quy hàm xn cho các giá trị từ 0 đến n-1.
Đồng thời ta cũng tốn một chi phí là c2 n cho vòng lặp của i từ 1 đến n
n-1
Þ T ( n) = c2 n + c3 + å T ( i )
i =0
ìT ( 0 ) = c1
ï
Phương trình đệ quy: í n-1
ïT ( n) = c2 n + c3 + å T ( i ), n > 0
î i =0
c, waste(n)
{ if (n==0) return 0;
[ for (i=1 to n)
for (j=1 to i)
print i,j,n; ] // Tạm gọi đoạn chương trình này là P
for (i=1 to 3)
waste(n/2);
}
Giải
( ) ( )
Đặt T n là tổng chi phí khi thực hiện waste(n). Dễ thấy T 0 = c1 (hằng số)
ì n
ïsosanh ( n) = n + 1 + å ( i + 1) =
( n + 1)( n + 4 )
ï i =1 2
à TP = sosanh(n) + print(n)
í
ï n n ( n + 1)
ï print ( n) = å i = 2
î i =1
Ta chỉ xem xét đến bậc cao nhất của n, do đó có thể viết TP = c2 n2
(Chỉ cần ghi c2n2 thôi để lúc giải nó dễ hơn, ghi đầy đủ thì khó giải)
( )
Đối với vòng lặp cuối, waste n / 2 được gọi đệ quy tổng cộng 3 lần.
() (
Từ đó ta suy ra: T n = 3T n / 2 + c2 n2 )
ìïT ( 0 ) = c1
Phương trình đệ quy: í
ïîT ( n) = 3T ( n / 2 ) + c2 n > 0
2
d, Lập phương trình truy hồi cho T(n) (là tổng số phép cộng cần thực hiện khi gọi Zeta(n))
Zeta(n)
{ if (n==0) Zeta = 6;
else
{ k = 0; Ret = 0;
while ( k £ n - 1 )
{ Ret = Ret + Zeta(k);
k = k + 1;
}
Zeta = Ret;
}
}
Giải:
Dễ thấy với n = 0, ta có T 0 = 0( )
Với n > 0, hàm thực hiện gọi đệ quy cho các giá trị Zeta từ 0 đến n-1
Bên cạnh đó, ta đếm nhanh được tổng số phép cộng cho vòng lặp while ( k £ n - 1 ) (không
tính Zeta(k)) là 2n
ìT ( 0 ) = 0
ï
Phương trình truy hồi cho T(n): í n-1
ïT ( n) = å T ( i ) + 2n, n ³ 1
î i =0
ìT (1) = 1
a, ï
í ænö
ïT ( n ) = 2T ç ÷+n
î è2ø
é æ n ö nù
T ( n ) = 2 ê 2T ç ÷ + ú + n
ë è 4 ø 2û
æ nö
T ( n) = 2 2 T ç 2 ÷ + 2 n
è2 ø
é æ n ö nù
T ( n ) = 22 ê 2T ç ÷ + ú + 2n
ë è 8 ø 4û
ænö
T (n) = 23 T ç 3 ÷ + 3n
è2 ø
ænö
T (n) = 2i T ç i ÷ + in
è2 ø
n
Quá trình sẽ dừng lại khi đạt tới T(1) Þ i
= 1 Û n = 2i Û i = log 2 n
2
Khi đó: T (n) = nT (1) + n log 2 n. Hay T ( n ) = n + n log 2 n
ìT (1) = 1
b, ï
í ænö 2
ïT (n) = 2T ç 2 ÷ + n
î è ø
é æ n ö æ n ö2 ù
T ( n ) = 2 ê2T ç ÷ + ç ÷ ú + n2
ëê è 4 ø è 2 ø ûú
ænö n2
T (n) = 22 T ç ÷ + n2 +
è4ø 2
é æ n ö æ n ö2 ù 2 n 2
T ( n ) = 2 ê 2T ç ÷ + ç ÷ ú + n +
2
ëê è 8 ø è 4 ø ûú 2
2 2
ænö 2 n n
T (n) = 2 T ç 3 ÷ + n + + 2
3
è2 ø 2 2
i -1 k
ænö æ1ö
T (n) = 2 T ç i ÷ + n 2 å ç ÷
i
è2 ø k =0 è 2 ø
æ nö æ 1ö
T ( n) = 2i T ç i ÷ + n2 .2. ç 1 - i ÷
è2 ø è 2 ø
n
Quá trình sẽ dừng lại khi đạt tới T(1) Þ i
= 1 Û 2i = n
2
Khi đó: T (n) = nT (1) + 2n 2 æç1 - ö÷. Hay T n = 2n2 - n
1
()
è nø
ìT (1) = 1
c, ï
í ænö 3
ïT (n) = 8T ç 2 ÷ + n
î è ø
é ænö ænö ù
3
T (n) = 23 ê23 T ç ÷ + ç ÷ ú + n3
êë è 4 ø è 2 ø úû
æ nö
T (n) = 22.3 T ç 2 ÷ + 2n3
è2 ø
é 3 æ n ö æ n ö3 ù
T (n) = 2 ê2 T ç ÷ + ç 2 ÷ ú + 2n3
2.3
ëê è 8 ø è 2 ø ûú
ænö
T (n) = 23.3 T ç 3 ÷ + 3n3
è2 ø
ænö
T (n) = 23.i T ç i ÷ + in3
è2 ø
n
Quá trình sẽ dừng lại khi tới T(1) Þ i
= 1 Û n = 2i Û i = log 2 n
2
Khi đó: T (n) = n T (1) + n log 2 n. Hay T ( n) = n3 (1 + log2 n)
3 3
ìïT ( 0 ) = 1, T (1) = 2
a, í
ïîT ( n) = 4T ( n - 1) - 3T ( n - 2 )
T ( n) = 4T ( n - 1) - 3T ( n - 2 ) Û T ( n) - 4T ( n - 1) - 3T ( n - 2 ) = 0
()
Đặt xn = T n , ta có xn - 4 xn-1 + 3xn-2 = 0
()
Do đó, T n = c1 x1n + c2 x2 n = c1 + c2 .3n
ì 1
ìïc1 + c2 = 1 ïïc1 = 2
Với T ( 0 ) = 1 và T (1) = 3, ta có hệ phương trình: í Þí
îïc1 + 3c2 = 2 ïc = 1
ïî 2 2
Vậy T ( n) =
1 1 n 1 n
(
+ .3 = 3 + 1 , "n ³ 0
2 2 2
)
ìïT ( 0 ) = 0, T (1) = 1, T ( 2 ) = 2
b, í
ïîT ( n) = 4T ( n - 1) - 5T ( n - 2 ) + 2T ( n - 3 )
T ( n) = 4T ( n - 1) - 5T ( n - 2 ) + 2T ( n - 3 )
Û T ( n) - 4T ( n - 1) + 5T ( n - 2 ) - 2T ( n - 3 ) = 0
()
Đặt xn = T n , ta có xn - 4 xn-1 + 5xn-2 - 2 xn-3 = 0
( )( )
2
Phương trình đặc trưng: x3 - 4 x2 + 5x - 2 = 0 Û x - 2 x - 1 = 0
() ( )
Do đó, T n = c1 x1n + c2 n + c3 x2 n = c1 .2n + c2 n + c3
ìT ( 0 ) = 0 ìc + 0 + c = 0 ìc1 = 0
ïï ï
1 3
ï
Ta có hệ phương trình: íT (1) = 1 Þ í2c1 + c2 + c3 = 1 Þ íc2 = 1
ï ï ï
ïîT ( 2 ) = 2 î4c1 + 2c2 + c3 = 2 îc3 = 0
()
Vậy, T n = n, "n ³ 0
C. Hàm sinh
+¥
1. an = 1 Þ G ( x ) = å xn = 1
n= 0 1- x
+¥
2. an = n Þ G ( x ) = å nxn = x
(1 - x )
2
n= 0
+¥
1
3. an = n + 1 Þ G ( x ) = å ( n + 1) xn =
(1 - x )
2
n= 0
+¥
4. an = ( -1) Þ G ( x ) = å ( -1) xn = 1
n n
n= 0 1+ x
+¥
1
5. an = ( n + 1) a n Þ G ( x ) = å xna n ( n + 1) =
(1 - a x )
2
n= 0
ìïT ( 0 ) = C1
a, í
ïîT ( n) = T ( n - 1) + C2 , n > 0
+¥ +¥
f ( x ) = å T ( n) xn = T ( 0 ) + å T ( n) xn
n= 0 n=1
+¥
f ( x ) = C1 + å éëT ( n - 1) + C2 ùû xn
n=1
+¥ +¥
f ( x ) = å T ( n - 1) xn + C2 å xn + C1
n=1 n=1
+¥
æ +¥ ö
f ( x ) = xå T ( n - 1) xn-1 + C2 ç å xn - 1÷ + C1
n=1 è n=0 ø
æ 1 ö
f ( x ) = xf ( x ) + C2 ç - 1 ÷ + C1
è 1- x ø
1
f ( x ) = C2
x
+ C1 .
(1 - x )
2
(1 - x )
+¥ +¥ +¥
f ( x ) = C2 å nxn + C1 å xn = å (C2 n + C1 ) xn
n= 0 n= 0 n= 0
()
Vậy, T n = C1 + nC2 , "n ³ 0
ìïT ( 0 ) = 1, T (1) = 2
b, í
ïîT ( n) = 7T ( n - 1) - 12T ( n - 2 ) , n ³ 2
+¥ +¥
f ( x ) = å T ( n) xn = T ( 0 ) + xT (1) + å T ( n) xn
n= 0 n=2
+¥
f ( x ) = 2 x + 1 + å éë7T ( n - 1) - 12T ( n - 2 )ùû xn
n=2
+¥ +¥
f ( x ) = 2 x + 1 + 7å T ( n - 1) xn - 12å T ( n - 2 ) xn
n=2 n=2
æ +¥ ö +¥
f ( x ) = 2 x + 1 + 7 ç å T ( n - 1) xn - xT ( 0 ) ÷ - 12 x2 å T ( n - 2 ) xn-2
è n=1 ø n= 2
( )
f ( x ) = 2 x + 1 + 7 xf ( x ) - x - 12 x2 f ( x )
1 - 5x 2 1
f ( x) = = -
12 x - 7 x + 1 1 - 3 x 1 - 4 x
2
+¥ +¥ +¥
f ( x ) = 2å ( 3x ) - å ( 4 x ) = å 2.3n - 4n xn ( )
n n
n= 0 n= 0 n= 0
()
Vậy, T n = 2.3n - 4n , "n ³ 0
ìïT ( 0 ) = 3
c, í
ïîT ( n + 1) = T ( n) + 2 ( n + 2 ) , n ³ 0
() (
Hay T n = T n - 1 + 2n + 2, n ³ 1 )
Hàm sinh của dãy vô hạn T ( n) { }
+¥
là:
n= 0
+¥ +¥
f ( x ) = å T ( n) xn = T ( 0 ) + å T ( n) xn
n= 0 n=1
+¥
f ( x ) = 3 + å éëT ( n - 1) + 2n + 2 ùû xn
n=1
+¥ +¥ +¥
f ( x ) = 3 + å T ( n - 1) xn + 2å nxn + 2å xn
n=1 n=1 n=1
æ 1 ö
f ( x ) = 3 + xf ( x ) + 2
x
+ 2ç - 1÷
(1 - x ) è 1- x ø
2
2x 2x 3
f ( x) = + +
(1 - x ) (1 - x ) 1- x
3 2
2x - 2 + 2 2x 3
f ( x) = + +
(1 - x )
3
(1 - x )
2
(1 - x )
-2 2 2x 3
f ( x) = + + +
(1 - x ) (1 - x ) (1 - x ) 1- x
2 3 2
2 2x - 2 3
f ( x) = + +
(1 - x ) (1 - x )
3 2
(1 - x )
2 2 3
f ( x) = - +
(1 - x ) 1- x 1- x
3
2 1
f ( x) = +
(1 - x ) 1- x
3
+¥ +¥
f ( x ) = å ( n + 1)( n + 2 ) xn + å xn
n= 0 n= 0
+¥
(
f ( x ) = å n2 + 3n + 3 xn
n= 0
)
()
Vậy, T n = n2 + 3n + 3, "n ³ 0
1
Trong trường hợp không biết công thức của thì đi tìm dựa trên công thức đã có
(1 - x )
3
+¥
1 1 1
Tương tự với sẽ là . Ta có = å ( n + 1) xn . Đạo hàm 2 vế:
(1 - x ) (1 - x ) (1 - x )
3 2 2
n= 0
+¥ +¥ +¥
2
= å n ( n + 1) x n-1
. Đổi biến m = n - 1à å n n + 1 xn-1 = ( ) å ( m+ 1)( m+ 2 ) x m
(1 - x )
3
n= 0 n= 0 m=-1
+¥ +¥
m = -1 Þ ( m + 1)( m + 2 ) xm = 0 ® å ( m+ 1)( m+ 2 ) xm = å ( m+ 1)( m+ 2 ) xm
m=-1 m= 0
+¥
2
Suy ra = å ( n + 1)( n + 2 ) xn
(1 - x )
3
n= 0
Bước 3: Lập bảng lưu trữ kết quả cho bài toán ban đầu.
Xét ví dụ: dãy 4 3 1 2 6 3 4 (n = 7)
i 1 2 3 4 5 6 7
a 4 3 1 2 6 3 4
m 1
- Xét i = 1 à m[1] = 1
- Xét i = 2, a[2] = 3 không lập được thành dãy tăng với bất kì phần tử nào khác trước đó
à m[2] = 1
- Xét i = 3, a[3] = 1 không lập được thành dãy tăng với bất kì phần tử nào khác trước đó
à m[3] = 1
- Xét i = 4, a[4] = 2
j = 3, a[j] = 1 < 2
à m[4] = m[3] + 1 = 2
- Xét i = 5, a[5] = 6
+ j = 1, a[j] = 4 < 6 à m[1] + 1 = 2
+ j = 2, a[j] = 3 < 6 à m[2] + 1 = 2
+ j = 3, a[j] = 1 < 6 à m[3] + 1 = 2
+ j = 4, a[j] = 2 < 6 à m[4] + 1 = 3
m[5] = max {2,2,2,3} = 3
Thực hiện tương tự cho i = 6 và i = 7
i 1 2 3 4 5 6 7
a 4 3 1 2 6 3 4
m 1 1 1 2 3 3 4
Bước 4: Xác định kết quả cho bài toán ban đầu.
{ }
longest = max m[i ] = max {1,1,1,2,3,3,4} = 4
1£i £ n
Trong trường hợp cần tìm dãy con tăng, ta sử dụng thêm 1 mảng để lưu vết kết quả.
i 1 2 3 4 5 6 7
a 4 3 1 2 6 3 4
m 1 1 1 2 3 3 4
v -1 -1 -1 3 4 4 6
v[i] là chỉ số của phần tử cuối cùng trong dãy tăng kết thúc bởi phần tử a[i]
Trong trường hợp dãy chỉ có 1 phần tử, mặc định v[i] = -1
Ở trên, index của phần tử cuối cùng trong dãy tăng dài nhất là 7, từ đó ta có:
v[7] = 6 à v[6] = 4 à v[4] = 3 à v[3] = -1 (kết thúc)
Dãy cần tìm: a[3] , a[4], a[6], a[7] cũng chính là 1 2 3 4
Câu 2: bài toán chuỗi con chung dài nhất
Input: 2 chuỗi a và b có độ dài lần lượt là m và n
Output: 1 số nguyên dương x cho biết độ dài của chuỗi con chung dài nhất và chuỗi con chung dài
nhất đó
Giải
Gọi c là chuỗi con chung được tạo thành từ a và b
a(x,y) là chuỗi con được tạo thành bằng các kí tự từ vị trí x đến y trong chuỗi a
Bước 1: phân tích đặc trưng Optimal substructure
- Chưa xét đến chuỗi con chung tìm được có phải là dài nhất hay không, ta xem xét đến việc
tìm chuỗi con chung giữa 2 chuỗi a và b
Giả sử rằng ta tìm chuỗi con chung giữa 2 chuỗi a(1,i) và b(1,j) với 1 £ i £ m,1 £ j £ n
+ Nếu kí tự a[i] và b[j] giống nhau, ta biết kí tự này sẽ nằm trong c. Như vậy, chuỗi c sẽ
được ghép từ kí tự a[i] với chuỗi chung tìm được từ a(1,i-1) và b(1,j-1). Ta sẽ tiếp tục xem
xét 2 chuỗi này.
+ Nếu a[i] # b[j], a[i] hoặc b[j] không được chọn, ta sẽ xem xét chuỗi a(1,i-1) với b(1,j),
hoặc chuỗi a(1,i-1) với b(1,j-1)
Các việc xem xét giữa các cặp chuỗi như trên đều là bài toán con của việc tìm chuỗi chung
giữa 2 chuỗi a(1,i) và b(1,j)
Nhận xét 1: lời giải của bài toán gốc có sự kết hợp lời giải của các bài toán con
- Khi xét đến yêu cầu chuỗi chung phải là dài nhất, việc xét các cặp chuỗi theo từng trường
hợp như trên đều phải chọn ra chuỗi chung dài nhất.
Ví dụ, với chuỗi a = “abcde” (m=5) và b = “adef” (n=4)
Giả sử ta đã biết chuỗi con chung dài nhất của 2 chuỗi này là c = “ade”
Khi xét a(1,5) = “abcde” và b(1,3) = “ade”, ta có a[5] = b[3] = “e”, “ad” chính là chuỗi
con chung dài nhất khi xét a(1,4) = “abcd’ và b(1,2) = “ad”
Nhận xét 2: lời giải tối ưu của bài toán gốc chứa đựng trong đó lời giải tối ưu của bài toán
con
Bước 2: Lập phương trình quy hoạch động
- Xuất phát từ việc xét các trường hợp như đã nói ở trên
- Gọi l[i][j] là độ dài của chuỗi con chung dài nhất khi xét a(1,i) và b(1,j)
- Nếu a[i] = b[j], ta sẽ có l[i][j] = 1 + l[i-1][j-1] (do l[i-1][j-1] lúc này là độ dài của chuỗi
con chung dài nhất khi xét a(1,i-1) và b(1,j-1))
- Nếu a[i] # b[j], ta sẽ xem xét chuỗi a(1,i-1) với b(1,j) hoặc a(1,i) với b(1,j-1) và a(1,i-1).
l[i][j] lúc này chính bằng chuỗi con chung dài hơn khi xét chuỗi con chung dài nhất của 2
cặp chuỗi trên. Nói cách khác, l[i][j] = max{l[i][j-1]; l[i-1][j]}
- Phương trình quy hoạch động:
+ Nếu tồn tại giá trị 1<= i <= m sao cho a[i] = b[1] và i phải nhỏ nhất, ta có
ì1, if j ³ i
l [ j ][1] = í . Ngược lại, l[i][1] = 0 với 1<= i <= m
î0, if j < i
+ Nếu tồn tại giá trị 1<= i <= n sao cho a[1] = b[i] và i phải nhỏ nhất, ta có
ì1, if j ³ i
l [1][ j ] = í . Ngược lại, l[1][i] = 0 với 1<= i <= n
î 0, if j < i
+ Nếu tồn tại giá trị 1<= i <= n mà ô a[1][i] không an toàn và i phải nhỏ nhất, ta có
ì0, if j ³ i
m[1][ j ] = í . Ngược lại, m[1][i] = 1 với 1<= i <= n
î1, if j < i
- Xét ví dụ n = 4
1 2 3 4
1 1 1 1 1
2 1
3 1
4 0
- Với i = 2, j = 2, ô a[2][2] không an toàn nên m[2][2] = 0
- Với i = 2, j = 3, ô a[2][3] an toàn, ta có m[2][3] = m[2][2] + m[1][3] = 0 + 1 = 1.
Tức là chỉ có 1 đường đi an toàn đến ô a[2][3]
- Thực hiện tương tự cho các ô còn lại
1 2 3 4
1 1 1 1 1
2 1 0 1 2
3 1 1 2 0
4 0 1 3 3
Bước 4: Xác định kết quả của bài toán ban đầu
- Kết quả bài toán là m[4][4] = 3, tức là có 3 đường đi an toàn đến đích