Thiết kếthuậttoán Lê Sỹ Vinh Bộ môn Khoa Học Máy Tính – Khoa CNTT ðại Học Công Nghệ - ðHQGHN Email: vinhioi@yahoo.com Chia ðể Trị (Divide and Conquer) 1. Chia bài toán lớn thành các bài toán có kích thước nhỏ 2. Giải các bài toán có kích thước nhỏ 3. Kết hợp nghiệm của các bài toán có kích thước nhỏ ñể giải 3. Kết hợp nghiệm của các bài toán có kích thước nhỏ ñể giải bài toán lớn Ví dụ: Dãy số Fibonacci Dãy Fibonacci: 0 1 2 3 5 8 13… f(0) = 0 f(1) = 1 f(k) = f(k-1) + f(k-2) Fibonacci_DAC (k) { if (k == 0) return 0 else if (k == 1) return 1 else return Fibonacci _DAC (k-1) + fibonacci_DAC (k-2) } Nhận xét: Các bài toán nhỏ ñược giải quyết dựa vào những bài toán nhỏ hơn giống nhau. Quy hoạch ñộng (Dynamic programming) • Giống phương pháp ‘chia-ñể-trị’ (divide-and-conquer) là giải quyết bài toán lớn dựa vào kết quả các bài toán con. • ðiểm khác biệt là quy hoạch ñộng lưu lại nghiệm của tất cả các bài toán con, mỗi bài toán con chỉ phải tính toán1 lần. • Quy hoach ñộng thường ñược dùng ñể giải quyết những bài toán liên quan ñến tối ưu hóa (tìm nghiệm tốt nhất). Ví dụ: Dãy số Fibonacci int fib[N]; for (int i = 0; i <= N; i ++) fib[i] = -1; fib[0] = 0; fib[1] = 1; int fibonacci (int k) { if (fib[k] == -1) fib[k] = fibonacci (k-1) + fibonacci (k-2); return fib[k]; } Cấu trúc chung của phương pháp quy hoạch ñộng 1. ðưa ra cách tính nghiệm của các bài toán con ñơn giản 2. Tìm công thức xây dựng nghiệm của bài toán thông qua nghiệm của các bài toán con 3. Thiếtkế bảng ñể lưu nghiệm của các bài toán 4. Tính nghiệm của các bài toán từ nhỏ ñến lớn4. Tính nghiệm của các bài toán từ nhỏ ñến lớn 5. Xây dựng nghiệm của bài toán cần tìm từ bảng Ví dụ: Bài toán cái ba lô Có N ñồ vật, ñồ vật i có khối lượng w i và giá trị t i . Một tên trộm có 1 chiếc ba lô có thể mang ñược không qúa M kg. Hãy tìm cách mang một số ñồ vật ñể tổng giá trị lấy ñược là lớn nhất. Biết rằng, w i nguyên dương nhỏ hơn 101, M nguyên dương nhỏ hơn 1001. Ví dụ N = 4, M = 10 i 1 2 3 4 w i 5 4 6 3 t i 1 4 3 5 Ví dụ: Dãy con chung Cho hai dãy số A = (a 1 ,…,a n ) và B = (b 0 , ,b m ), tìm dãy số C = (c 0 , ,c k ) sao cho C là dãy con của cả A và B, và C dài nhất có thể . Ví dụ: A = (3, 5, 1, 3, 5, 5, 3) B = (1, 5, 3, 5, 3, 1) C = (5, 3, 5, 3) hoặc (1, 3, 5, 3) hoặc (1, 5, 5, 3) Ví dụ: Dãy con liền nhau tổng lớn nhất Cho dãy số A = (a 1 ,…,a n ), tìm dãy con liền nhau (a i , a i+1 ,…,a j-1 , a j ) với tổng lớn nhất. Ví dụ: A = (-3, 5, -4, 3, 2, -4, 1) Dãy con liền nhau tổng lớn nhất: (5, -4, 3, 2) Ví dụ: Chia kẹo Có N gói kẹo, gói kẹo i có a i cái. Hãy chia N gói kẹo trên thành 2 ñống sao cho chênh lệnh giữa tổng số kẹo của hai ñống là ít nhất. Lưu ý là không ñược chia nhỏ các gói kẹo ra. Ví dụ: N = 5 1 3 4 9 5 Chia thành: 1 9 và 3 4 5 . dương nhỏ hơn 10 1, M nguyên dương nhỏ hơn 10 01. Ví dụ N = 4, M = 10 i 1 2 3 4 w i 5 4 6 3 t i 1 4 3 5 Ví dụ: Dãy con chung Cho hai dãy số A = (a 1 ,…,a n ). giải 3. Kết hợp nghiệm của các bài toán có kích thước nhỏ ñể giải bài toán lớn Ví dụ: Dãy số Fibonacci Dãy Fibonacci: 0 1 2 3 5 8 13 … f(0) = 0 f (1) = 1 f(k)