3. 3
Đệ quy
Khái niệm: Một đối tượng là đệ quy nếu nó được định
nghĩa qua chính nó hoặc một đối tượng khác cùng dạng
với chính nó bằng quy nạp.
Phân loại: Có 2 loại đối tượng đệ quy.
Đệ quy trực tiếp: Đối tượng A được mô tả trực tiếp qua
chính đối tượng A.
Ví dụ: A mô tả qua A, B, C. Trong đó: B, C không chứa A.
Đệ quy gián tiếp: Đối tượng A được mô tả gián tiếp qua
đối tượng A.
Ví dụ: A mô tả qua B, C, D. Trong đó: B được mô tả qua A và E,
còn C và D không chứa A.
4. 4
Minh hoạ đệ quy
1) Đệ quy trực tiếp 2) Đệ quy gián tiếp
A
B C
A
A A
C
E
B
D
5. 5
Mô tả đệ quy
Điểm mạnh của đệ quy: Cho phép mô tả 1 tập lớn các
đối tượng bằng 1 số ít các mệnh đề hoặc mô tả 1 GT
phức tạp bằng 1 số ít các thao tác (1 chương trình con
đệ quy).
Mô tả đệ quy: gồm 2 phần
Phần neo: Mô tả các trường hợp suy biến của đối tượng
(giải thuật) qua 1 cấu trúc (thao tác) cụ thể xác định.
Phần đệ quy: Mô tả đối tượng (giải thuật) trong trường
hợp phổ biến thông qua chính đối tượng (giải thuật) đó 1
cách trực tiếp (đệ quy trực tiếp) hoặc gián tiếp (đệ quy
gián tiếp).
Chú ý: Nếu không có phần neo thì đối tượng được mô tả
có cấu trúc lớn vô hạn (giải thuật lặp không dừng)!
6. 6
Một số mô tả đệ quy thường gặp
1. Tập số tự nhiên N:
0 là số tự nhiên. {phần neo}
X là số tự nhiên nếu X – 1 là số tự nhiên. {phần đệ quy}
2. Giai thừa của 1 số tự nhiên N:
0! = 1 {phần neo}
Nếu N > 0 thì N! = N * (N – 1)! {phần đệ quy}
3. Ước số chung lớn nhất (USCLN) của 2 số tự nhiên A
và B không đồng thời bằng 0 (A2 + B2 > 0)
USCLN(A, 0) = A {phần neo}
USCLN(A, B) = USCLN(B, A mod B) {phần đệ quy}
7. 7
Câu hỏi kiểm tra nhận thức
Câu hỏi 1:
Giải thích mô tả đệ quy USCLN(A, B). Minh hoạ quá
trình thực hiện với:
1. A = 126 và B = 72.
2. A = 72 và B = 126.
Đáp án:
Giải thích:
Nếu B = 0 thì USCLN(A, B) = A.
Nếu B ≠ 0 thì thay A bằng B, thay B bằng A mod B
rồi lặp lại quá trình thực hiện.
USCLN(A, B) = USCLN(B, A mod B)
9. 9
Một số bài toán đệ quy điển hình
Bài toán tìm nghiệm gần đúng: của phương trình f(x)=0
trên đoạn [a, b] với sai số c, biết f(x) liên tục trên [a, b].
Bài toán “Tháp Hà Nội”: Chuyển một chồng đĩa N đĩa
với kích thước khác nhau từ cột A sang cột C theo cách:
Mỗi lần chỉ chuyển 1 đĩa .
Khi chuyển có thể dùng cột trung gian B.
Trong suốt quá trình chuyển, các chồng đĩa ở các cột luôn
được xếp đúng (đĩa có kích thước bé đặt trên đĩa có kích
thước lớn).
Bài toán “N quân Hậu”: Xếp N quân hậu trên bàn cờ
hình vuông kích thước N x N sao cho trên mỗi đường
chéo, đường ngang, đường dọc chỉ có đúng 1 quân Hậu.
10. 10
Đặc điểm hàm đệ quy
Khái niệm: một chương trình con mô tả giải thuật đệ
quy gọi là chương trình con đệ quy, hay hàm đệ quy.
Pascal (hàm, thủ tục), C/C++ (hàm có kiểu, hàm void).
Đặc điểm: một hàm đệ quy có 3 đặc điểm sau
1. Có lời gọi đến chính nó: trong thân hàm đệ quy có chứa
lời gọi hàm tới chính hàm đệ quy đó.
2. Kích thước bài toán giảm dần: mỗi lần có lời gọi hàm đệ
quy thì kích thước của bài toán đã thu nhỏ hơn trước.
3. Có trường hợp suy biến: là trường hợp đặc biệt mà khi
xảy ra thì bài toán sẽ được giải quyết theo 1 cách khác
hẳn và quá trình gọi hàm đệ quy cũng kết thúc.
Kích thước bài toán giảm dần đảm bảo có trường hợp suy biến!
11. 11
Đặc điểm hàm đệ quy
Phân loại: Có 2 loại hàm đệ quy, tương ứng với 2 loại
mô tả đệ quy.
Đệ quy trực tiếp: trong thân hàm A có chứa lời gọi hàm
đến chính A (thường gặp).
Bài toán giai thừa, USCLN, Fibonacci, Ackerman, tổ hợp,…
Đệ quy gián tiếp: trong thân hàm A chứa lời gọi hàm đến
hàm B, và trong thân hàm B lại chứa lời gọi hàm đến A
(ít gặp).
Giả thiết Collatz,...
12. 12
Đệ quy gián tiếp: Giả thiết Collatz
Collatz đưa ra giả thuyết rằng:
“Với một số nguyên dương X bất kỳ, nếu X chẵn thì ta
gán X = X / 2; nếu X lẻ thì ta gán X = X * 3 + 1 thì sau
một số hữu hạn bước, ta sẽ có X = 1”.
Với X = 10, các bước tiến hành như sau:
1. X = 10 //X chẵn X = 10 / 2
2. X = 5 //X lẻ X = 5 * 3 + 1
3. X = 16 //X chẵn X = 16 / 2
4. X = 8 //X chẵn X = 8 / 2
5. X = 4 //X chẵn X = 4 / 2
6. X = 2 //X chẵn X = 2 / 2
7. X = 1 //Kết thúc
13. 13
Đệ quy gián tiếp: Giả thiết Collatz
Bài toán (dựa trên khẳng định giả thuyết Collatz là
đúng):
“Cho trước số 1 cùng với hai phép toán * 2 và / 3, hãy sử
dụng một cách hợp lý hai phép toán đó để biến số 1
thành một số nguyên dương X cho trước.”
Ví dụ: X = 10 ta có biểu diễn 1 * 2 * 2 * 2 * 2 / 3 * 2 = 10.
Giải thuật:
Để biểu diễn X chia 2 trường hợp:
Nếu X chẵn, thì tìm cách biểu diễn số X / 2 và viết thêm
phép toán * 2 vào cuối.
Nếu X lẻ, thì tìm cách biểu diễn số X * 3 + 1 và viết thêm
phép toán / 3 vào cuối.
15. 15
Đệ quy gián tiếp: Giả thiết Collatz
//In ra cách biểu diễn số X
void XuLySo(int X)
{
if (X == 1)
printf(“%d”, X);
else
if (X % 2 == 1) XuLySoLe(X);
else
XuLySoChan(X);
}
16. 16
2.2. Thiết kế giải thuật đệ quy
2.2.1. Hàm N!
2.2.2. Dãy số Fibonacci
2.2.3. Chú ý
17. 17
2.2.1. Hàm N!
Mô tả đệ quy:
1 nếu N = 0 (phần neo)
N! =
N * (N - 1)! nếu N > 0 (phần đệ quy)
Hàm đệ quy tính N! :
long GT(int N)
{
if (N == 0) return 1;
return N * GT(N – 1);
}
18. 18
3 đặc điểm đệ quy của hàm N!
Đặc điểm:
Đối chiếu với đặc điểm hàm đệ quy:
Có lời gọi đến chính nó: hàm đệ quy GT(N) gọi đến hàm
GT(N – 1).
return N * GT(N – 1)
Kích thước bài toán giảm dần: sau mỗi lần gọi đệ quy,
giá trị của dữ liệu vào N giảm đi 1.
Có trường hợp suy biến: là trường hợp N = 0. Khi đó,
hàm GT(N) trả về giá trị 1 và đệ quy kết thúc.
if (N == 0) return 1;
19. 19
GT lặp tính N!
Khái niệm:
Phương pháp sử dụng vòng lặp để giải bài toán đệ quy
gọi là khử đệ quy.
Giải thuật mô tả phương pháp khử đệ quy gọi là giải
thuật lặp.
Đặc điểm:
Ưu điểm:
Thường hiệu quả hơn đệ quy do không phải thực hiện nhiều lần
các thao tác: gọi hàm, cấp phát và giải phóng các biến cục bộ.
Không bị tràn bộ nhớ stack như đệ quy do không phải lưu trữ các
lời gọi trước.
Nhược điểm:
Việc tìm ra GT lặp thường khó khăn hơn nhiều GT đệ quy.
Việc lập trình thường phức tạp.
20. 20
GT lặp tính N!
Mô tả không đệ quy: bài toán N! có thể mô tả theo
cách không đệ quy như sau:
N! = 1 * 2 * … * (N – 1) * N
N! là tích của N số tự nhiên liên tiếp từ 1 đến N!
Giải thuật lặp:
long GT(int N)
{
long p = 1;
for(int i = 2; i <= N; i++)
p = p * i;
return p;
}
Giải thuật lặp tính N! rất đơn giản!
21. 21
Đánh giá độ phức tạp giải thuật
Phân tích đánh giá độ phức tạp của giải thuật lặp tính N!:
B1: Xác định phép toán tích cực:
p = p * i;
B2: Số lần thực hiện của phép toán tích cực là:
1 + 1 + … + 1 = N – 1 (lần)
B3: Kết luận độ phức tạp của giải thuật:
T(N) = O(N)
22. 22
2.2.2. Dãy số Fibonacci
Khái niệm: Dãy số Fibonacci bắt nguồn từ bài toán cổ
về việc sinh sản của các cặp thỏ.
Dãy số Fibonacci là mô hình của rất nhiều hiện tượng tự
nhiên và cũng được sử dụng nhiều trong tin học.
Bài toán:
1. Các con thỏ không bao giờ chết.
2. Hai tháng sau khi ra đời, 1 cặp thỏ mới sẽ sinh ra 1 cặp
thỏ con gồm (1 đực, 1 cái).
3. Khi đã sinh con rồi thì cứ mỗi tháng tiếp theo chúng lại
sinh ra được 1 cặp thỏ con mới.
Yêu cầu: Từ 1 cặp thỏ mới ra đời thì đến tháng thứ N sẽ
có bao nhiêu cặp thỏ?
23. 23
Dãy số Fibonacci
Diễn giải quá trình sinh sản của thỏ:
Tháng thứ 1: 1 cặp (cặp ban đầu)
Tháng thứ 2: 1 cặp (cặp ban đầu vẫn chưa sinh)
Tháng thứ 3: 2 cặp (đã có thêm 1 cặp con)
Tháng thứ 4: 3 cặp (cặp đầu vẫn sinh thêm)
Tháng thứ 5: 5 cặp (cặp con bắt đầu sinh)
Tháng thứ 6: 8 cặp (cặp con vẫn sinh tiếp)
…
Tháng thứ N: ? cặp
Dãy số Fibonacci
1 1 2 3 5 8 … ?
24. 24
Công thức tính số Fibonacci F(N)
Tìm công thức tính số cặp thỏ ở tháng thứ N: F(N)
Nếu mỗi cặp thỏ ở tháng thứ (N - 1) đều sinh con thì:
F(N) = 2 * F(N – 1)
Do 2 tháng sau khi được sinh ra, thỏ mới sinh con, nên
trong các cặp thỏ ở tháng thứ (N–1) chỉ có những cặp đã
có ở tháng thứ (N – 2) mới sinh con ở tháng thứ N.
Do đó số cặp thỏ ở tháng thứ N sẽ là:
F(N) = F(N – 2) + F(N – 1)
Mô tả đệ quy: tính F(N).
1 nếu N ≤ 2 //phần neo
F(N) =
F(N – 2) + F(N – 1) nếu N > 2 //phần đệ quy
25. 25
GT đệ quy tính F(N)
Hàm đệ quy tính F(N):
long F(long N)
{
if (N <= 2) return 1;
return F(N – 2) + F(N – 1);
}
3 đặc điểm của hàm đệ quy:
1. Có lời gọi đến chính nó: return F(N – 2) + F(N – 1);
2. Kích thước bài toán giảm dần: N giảm thành N-1, N-2
3. Có trường hợp suy biến: F(1) = 1 và F(2) = 1
Chú ý: có 1 chi tiết hơi khác là trường hợp suy biến ứng
với 2 giá trị: F(1) = 1 và F(2) = 1
26. 26
Giải thuật lặp tính F(N)
Giải thuật lặp:
long F(long N)
{
if (N <= 2) return 1;
Fib1 = 1;
Fib2 = 1;
for(long i = 3; i <= N; i++)
{
Fibn = Fib1 + Fib2;
Fib1 = Fib2;
Fib2 = Fibn;
}
return Fibn;
}
27. 27
Đánh giá độ phức tạp giải thuật
Phân tích độ phức tạp của giải thuật lặp tính F(N):
B1: Xác định phép toán tích cực:
Fibn = Fib1 + Fib2;
Fib1 = Fib2;
Fib2 = Fibn;
B2: Xác định số lần thực hiện của phép toán tích cực:
1 + 1 + … + 1 = N – 2 (lần)
B3: Kết luận độ phức tạp của giải thuật lặp là:
T(N) = O(N)
28. 28
2.3. Một số dạng bài điển hình
2.3.1. Bài toán đếm
2.3.2. Bài toán liệt kê
2.3.3. Bài toán tối ưu
29. 29
Một số dạng bài điển hình
Bài toán đếm: trong tập các đối tượng cho trước, có bao
nhiêu đối tượng thỏa mãn những điều kiện nhất định.
Có bao nhiêu số nguyên tố không lớn hơn N?
Bài toán liệt kê: trong tập các đối tượng cho trước, liệt
kê cấu hình của tất cả những đối tượng thỏa mãn những
điều kiện nhất định.
Liệt kê các số nguyên tố không lớn hơn N?
Bài toán tối ưu: trong tập các đối tượng cho trước, tìm
cấu hình của đối tượng thỏa mãn những điều kiện nhất
định và là tốt nhất theo một tiêu chí cụ thể.
Tìm số nguyên tố lớn nhất trong các số nguyên tố không
lớn hơn N?
30. 30
2.3.1. Bài toán đếm
Bài toán đếm: trong tập các đối tượng cho trước, có bao
nhiêu đối tượng thỏa mãn những điều kiện nhất định.
Ví dụ:
Có bao nhiêu số nguyên tố không lớn hơn N?
Có bao nhiêu xâu nhị phân độ dài N không chứa xâu ‘00’?
Phương pháp giải:
Công thức toán học + nguyên lý đếm cơ bản (cộng, nhân, bù trừ).
Công thức truy hồi (phương trình truy hồi tuyến tính thuần nhất,
đệ quy, quy hoạch động).
Bài toán liệt kê: sử dụng phương pháp liệt kê để giải bài toán
đếm, chỉ được sử dụng khi không tìm ra cách giải nào khác.
Nhận xét:
Bài toán đếm thường xuyên xuất hiện trong các bài thi OLP vì có
nhiều khả năng cải tiến thuật giải để giảm thời gian chạy!
31. 31
2.3.1. Bài toán đếm
Bài toán: Xóa số (OLP Không chuyên 2012)
Cho dãy số nguyên không âm a1, a2, …, an. Người ta
tiến hành chọn ra 2 chỉ số i, j sao cho 1 ≤ i < j ≤ n và xóa
khỏi dãy 2 số ai, aj để tổng giá trị các số còn lại trong
dãy là số chẵn.
Yêu cầu: Cho dãy số a1, a2, …, an. Hãy đếm số lượng
cách chọn 2 chỉ số i, j thỏa mãn. Hai cách chọn khác
nhau nếu tồn tại một chỉ số khác nhau.
Dữ liệu: vào từ file văn bản DEL.INP:
Dòng 1: chứa số nguyên n (n ≤ 106).
Dòng 2: chứa n số nguyên không âm a1, a2, …, an (ai ≤ 109).
Kết quả: đưa ra file văn bản DEL.OUT một số nguyên là
số cách chọn 2 chỉ số thỏa mãn.
32. 32
2.3.1. Bài toán đếm
Ví dụ:
Giải thích:
Có 6 cách chọn 2 số (i, j) để xóa khỏi dãy để tổng còn lại là số
chẵn.
(1, 2) (1, 4)
(2, 3) (2, 5)
(3, 4)
(4, 5)
65
1 2 3 4 5
DEL.OUTDEL.INP
33. 33
2.3.1. Bài toán đếm
B1: Xác định bài toán
Vấn đề cần giải quyết: đếm số cách xóa các cặp (ai, aj)
để tổng còn lại là số chẵn.
Giả thiết: có n số nguyên a1, a2, …, an.
Yêu cầu: số nguyên là số cách xóa.
B2: Tìm cấu trúc dữ liệu
n: kiểu số nguyên 4 byte.
a: kiểu mảng 1 chiều của kiểu số nguyên 4 byte.
Biến kết quả kq: kiểu số nguyên 8 byte.
Chú ý: nếu mọi cách xóa 1 cặp (ai, aj) khỏi dãy số đều thỏa mãn
điều kiện tổng còn lại là số chẵn thì số cách xóa tối đa (n = 106)
là: n(n-1) / 2 = 5 * 1011 cách
34. 34
2.3.1. Bài toán đếm
B3: Tìm giải thuật
GT 1:
Ý tưởng: “vét cạn”, duyệt tất cả các phương án xóa số để tìm ra
số cách kq. Đây chính là ý tưởng của bài toán liệt kê.
Mô tả:
kq = 0; sum = 0; //Tính tổng dãy số a
for(i = 0; i < n; i++) sum = sum + a[i];
for(i = 0; i < n – 1; i++)
for(j = i + 1; j < n; j++)
{
tong = sum – a[i] – a[j]; //Tổng còn lại
if (tong % 2 == 0) kq = kq + 1; //Đếm
}
Đánh giá: Độ phức tạp GT 1 thuộc phân lớp N2.
35. 35
2.3.1. Bài toán đếm
GT 2:
Ý tưởng: sử dụng “nguyên lý đếm”.
Gọi sum là tổng các phần tử của dãy a[], x là số phần tử lẻ
y = n – x là số phần tử chẵn.
- Nếu sum chẵn thì phải xóa 2 số lẻ hoặc 2 số chẵn. Kết quả:
kq = x(x-1)/2 + y(y-1)/2
- Nếu sum lẻ thì phải xóa 1 số lẻ và 1 số chẵn. Kết quả:
kq = xy
36. 36
2.3.1. Bài toán đếm
Mô tả:
//B1: Tính tổng dãy số a và số phần tử lẻ x
sum = 0;
x = 0;
for(i = 0; i < n; i++)
{
sum = sum + a[i];
if (a[i] % 2 == 1) x = x + 1;
}
y = n – x; //Số phần tử chẵn
//B2: Áp dụng nguyên lý đếm
if(sum % 2 == 0) kq = x * (x – 1) / 2 + y * (y – 1) / 2;
else kq = x * y;
Đánh giá: Độ phức tạp GT 2 thuộc phân lớp N.
37. 37
2.3.2. Bài toán liệt kê
Bài toán liệt kê: trong tập các đối tượng cho trước, liệt
kê cấu hình của tất cả những đối tượng thỏa mãn những
điều kiện nhất định.
Bài toán liệt kê cũng thuộc lớp bài toán đếm!
Ví dụ:
Liệt kê các số nguyên tố không lớn hơn N?
Liệt kê các xâu nhị phân độ dài N không chứa xâu ‘00’?
Phương pháp giải:
Phương pháp sinh (generation): “hợp lý”, khó áp dụng.
Thuật toán quay lui (backtracking algorithms): phổ biến.
Nhận xét:
Bài toán liệt kê hiếm khi xuất hiện trong các bài thi OLP vì có thời
gian chạy lớn, khó có khả năng cải tiến thuật giải!
38. 38
Phương pháp sinh
Điều kiện áp dụng:
Có thể xác định được 1 thứ tự trên tập các cấu hình cần
liệt kê, cấu hình đầu tiên, cấu hình cuối cùng.
Xây dựng được thuật toán từ 1 cấu hình chưa phải cấu
hình cuối cùng, sinh ra cấu hình kế tiếp.
Mô tả:
<Xây dựng cấu hình đầu tiên>;
do {
<Liệt kê cấu hình hiện tại>;
<Sinh cấu hình kế tiếp từ cấu hình hiện tại>;
}
while (<Chưa phải cấu hình cuối cùng>)
39. 39
Phương pháp sinh
Bài toán: Liệt kê các xâu nhị phân độ dài N
Thứ tự: thứ tự từ điển (0, 1) tính từ phải sang trái.
Cấu hình đầu tiên: 0 0 … 0
Cấu hình cuối cùng: 1 1 … 1
Phương pháp sinh:
Xét xâu nhị phân từ phải sang trái, tìm số 0 đầu tiên.
Tìm thấy: thay 0 bằng 1, cho các phần tử phía sau vị trí đó bằng 0
Không tìm thấy: là cấu hình cuối cùng. Kết thúc.
Ví dụ: N = 5
Cấu hình hiện tại: 1 0 0 1 1
Tìm số 0 đầu tiên: 1 0 0 1 1
Thay 0 bằng 1: 1 0 1 1 1
Cấu hình kế tiếp: 1 0 1 0 0
40. 40
Phương pháp sinh
Bài toán: Liệt kê các tập con K phần tử
Thứ tự: thứ tự từ điển (1, 2, …, N) tính từ phải sang trái.
Cấu hình đầu tiên: 1 2 … K
Cấu hình cuối cùng: N-K+1 N-K+2 … N
Phương pháp sinh:
Xét tập con từ phải sang trái, tìm phần tử đầu tiên (x[i]) chưa đạt
giới hạn trên (N-K+i).
Tăng x[i] lên 1, các pt sau (x[j]) bằng giới hạn dưới (x[j-1]+1).
Không tìm thấy: là cấu hình cuối cùng. Kết thúc.
Ví dụ: N = 9, K = 5
Cấu hình hiện tại: 1 3 7 8 9
Tìm phần tử đầu tiên chưa đạt giới hạn trên: 1 3 7 8 9
Tăng phần tử tìm được x[i] lên 1: 1 4 7 8 9
Cấu hình kế tiếp: 1 4 5 6 7
41. 41
Phương pháp sinh
Bài toán: Dãy số (OLP Không chuyên 2008)
Một sinh viên Trường ĐH Kỹ thuật Công nghệ đang
nghiên cứu về bài toán dãy số: tìm số An của dãy A0,
A1, A2,…, trong đó
A0 = 0,
Ai là số nguyên dương nhỏ nhất lớn hơn Ai-1 và trong biểu diễn
thập phân của Ai không chứa các chữ số trong biểu diễn thập
phân của Ai với i ≥ 1.
Như vậy các phần tử đầu tiên của dãy A là:
50
14
41
13
…3022109876543210A[i]
…1211109876543210i
42. 42
Phương pháp sinh
Yêu cầu: Cho số tự nhiên n. Hãy tìm An.
Dữ liệu: vào từ file văn bản NUMSEG.INP trong đó
chứa duy nhất số n (0 ≤ n ≤ 500).
Kết quả: ghi ra file văn bản NUMSEG.OUT giá trị An.
Ví dụ:
00
3012
91127
NUMSEG.OUTNUMSEG.INP
43. 43
Thuật toán quay lui
Ý tưởng: Xây dựng cấu hình liệt kê x[1..n] bằng cách
thử tất cả các khả năng của từng phần tử x[i].
Cho x[1] nhận lần lượt các giá trị có thể. Với mỗi x[1]:
Cho x[2] nhận lần lượt các giá trị có thể. Với mỗi x[2]:
• …
Cho x[n] nhận lần lượt các giá trị có thể. Với mỗi
x[n], ta có 1 cấu hình x[1..n]
Nhận xét:
Ý tưởng của thuật toán quay lui là “duyệt toàn bộ”.
Có thể giải được hầu hết các bài toán tổ hợp.
Chỉ sử dụng thuật toán quay lui để giải các bài toán đếm,
tối ưu khi không còn lựa chọn nào khác.
44. 44
Thuật toán quay lui
Mô tả:
void try(i) //Cho x[i] nhận lần lượt các giá trị có thể
{
for (<Mọi giá trị V có thể gán cho x[i]>)
{
x[i] = V;
if (i == n)
<Thông báo cấu hình tìm được>;
else
try(i+1); //Gọi đệ quy để chọn x[i+1]
}
}
45. 45
Thuật toán quay lui
Điều kiện áp dụng:
Tìm được tập giá trị có thể của 1 phần tử x[i] bất kỳ trong
cấu hình x[1..n].
Đối với các bài toán tổ hợp, điều kiện này thường dễ
dàng tìm được!
Bài toán:
Liệt kê xâu nhị phân độ dài N: tập giá trị của 1 phần tử
x[i] trong xâu là (0, 1).
46. 46
2.3.3. Bài toán tối ưu
Bài toán tối ưu: trong tập các đối tượng cho trước, tìm
cấu hình của đối tượng thỏa mãn những điều kiện nhất
định và là tốt nhất theo một tiêu chí cụ thể.
Ví dụ:
Tìm số nguyên tố lớn nhất trong các số nguyên tố ≤ N?
Bài toán Mật độ giao thông – OLP 2012: tìm độ lệch của hai
đoạn đường có tình trạng giao thông giống nhau nhất?
Phương pháp giải: rất đa dạng
Phương pháp quy hoạch động (dynamic programming).
Thuật toán tham lam (greedy algorithms).
Thuật toán quay lui: kỹ thuật nhánh cận
Nhận xét:
Bài toán tối ưu thường xuyên xuất hiện trong các bài thi OLP,
cũng như trong các bài toán thực tế
47. 47
2.4. Câu hỏi ôn tập
1. Hàm Ackermann:
Cho mô tả đệ quy:
N + 1 nếu M = 0
Acker(M, N) = Acker(M – 1, 1) nếu N = 0
Acker(M – 1, Acker(M, N – 1)) còn lại
(Hàm Ackermann có đặc điểm là giá trị tăng rất nhanh khi
đối số M, N tăng, M và N là các giá trị nguyên)
a) Chỉ rõ phần neo và phần đệ quy trong mô tả.
b) Minh họa quá trình tìm Acker(1, 2).
c) Viết 1 hàm đệ quy tính giá trị của hàm này và chỉ rõ 3
đặc điểm của hàm đệ quy.
48. 48
2.4. Câu hỏi ôn tập
2. Bài toán Fibonacci:
Tìm phần tử thứ N trong dãy số Fibonacci.
a) Nêu mô tả đệ quy và chỉ rõ phần neo và phần đệ quy.
b) Viết 1 hàm đệ quy tính giá trị của hàm này và chỉ rõ 3
đặc điểm của hàm đệ quy.
c) Minh họa quá trình tìm F(5).
d) Viết hàm tính giá trị của hàm bằng giải thuật lặp. Phân
tích đánh giá giải thuật trong trường hợp trung bình.
49. 49
2.4. Câu hỏi ôn tập
3. Bài toán Ước số chung lớn nhất bằng phép chia:
Tìm USCLN(A, B) với A và B là các số tự nhiên không
đồng thời bằng 0.
a) Nêu mô tả đệ quy và chỉ rõ phần neo và phần đệ quy.
b) Viết 1 hàm đệ quy tính giá trị của hàm này và chỉ rõ 3
đặc điểm của hàm đệ quy.
c) Minh họa quá trình tìm USCLN(234, 198).
d) Viết hàm tính giá trị của hàm bằng giải thuật lặp. Phân
tích đánh giá giải thuật trong trường hợp tốt nhất.
50. 50
2.4. Câu hỏi ôn tập
4. Bài toán Ước số chung lớn nhất bằng phép trừ:
Tìm USCLN(A, B) với A và B là các số tự nhiên không
đồng thời bằng 0.
a) Nêu mô tả đệ quy và chỉ rõ phần neo và phần đệ quy.
b) Viết 1 hàm đệ quy tính giá trị của hàm này và chỉ rõ 3
đặc điểm của hàm đệ quy.
c) Minh họa quá trình tìm USCLN(126, 72).
51. 51
2.4. Câu hỏi ôn tập
5. Hàm tổ hợp: Cho mô tả đệ quy:
1 nếu K = 0 hoặc K = N
C(N, K) =
C(N – 1, K) + C(N – 1, K – 1) nếu 0 < K < N
a) Chỉ rõ phần neo và phần đệ quy trong mô tả.
b) Minh họa quá trình tìm C(5, 2).
c) Viết 1 hàm đệ quy tính giá trị của hàm này và chỉ rõ 3
đặc điểm của hàm đệ quy.
d) Viết hàm tính giá trị của hàm bằng giải thuật lặp theo
công thức sau:
K!K)!(N
N!
K)C(N,
−
=