Phương pháp quy hoạch động

In

Thứ hai, 25 Tháng 7 2011 14:52

     tinhoche11_06

 Thực hiện công số 534/SGDĐT-VP: V/v tập huấn kỹ năng lập trình và công tác bồi dưỡng học sinh giỏi Tin học trong hè 2011. Từ ngày 20/7/2011 đến 29/7/2011, tại trường THCS Huỳnh Khương Ninh đã diễn ra 2 đợt tập huấn dành riêng cho 2 khối THCS (20/7/2011 đến 24/7/2011) và THPT (25/7/2011 đến 29/7/2011) do Sở Giáo dục và Đào tạo chủ trì. Nhân dịp này tôi xin chia sẽ với các đồng nghiệp một bài viết sau:

Phương pháp quy hoạch động:

    Phương pháp quy hoạch động dùng để giải bài toán tối ưu có tính chất đệ quy, tức là việc tìm phương án tối ưu cho bài toán đó có thể đưa về tìm phương án tối ưu của một số hữu hạn các bài toán con. Đối với nhiều thuật toán đệ quy, nguyên lý chia để trị (devide and conquer) thường đóng vai trò chủ đạo trong việc thiết kế thuật toán. Để giải quyết một bài toán lớn, ta chia nó thành nhiều bài toán con cùng dạng với nó để có thể giải quyết độc lập. Trong phương pháp quy hoạch động, nguyên lý này càng được thể hiện rõ: Khi không biết cần phải giải bài những toán con nào, ta sẽ đi giải quyết tất cả các bài toán con và lưu trữ những lời giải hay đáp số của chúng với mục đích sử dụng lại theo một sự phối hợp nào đó để giải quyết những bài toán tổng quát hơn. Đó chính là điểm khác nhau giữa Quy hoạch động và phép đệ quy và cũng là nội dung Phương pháp quy hoạch động:tinhoche11_03

 


+Phép đệ quy bắt đầu từ bài toán lớn phân rã thành nhiều bài toán con và đi giải từng bài toán con đó. Việc giải từng bài toán con lại đưa về phép phân rã tiếp thành nhiều bài toán con nhỏ hơn và lại đi giải quyết bài toán nhỏ hơn đó bất kể nó đã được giải hay chưa.
+Quy hoạch động bắt đầu từ việc giải tất cả các bài toán nhỏ nhất (bài toán cơ sở) để từ đó từng bước giải quyết những bài toán lớn hơn, cho tới khi giải được bài toán lớn nhất (bài toán ban đầu).

Sau đây ta sẽ xét một ví dụ đơn giản và rất quen thuộc:
Ví dụ: Dãy Fibonacci là dãy số nguyên dương được định nghĩa như sau:
F[1]=F[2]=1;
Với mọi i: 3<=i: F = F[i-1] + F[i-2]
Hãy tính F[6]

Xét hai cách cài đặt chương trình bằng C++:

 

Code:

* Cách 1 (dùng đệ quy):tinhoche11_08


int F(int i)
{
    if (i<3)
        return 1;
    else
        return F(i-1) + F(i-2);
}
int main()
{
    cout<<F(6);
    return 0;
}

 

Code:

 * Cách 2 (dùng quy hoạch động):tinhoche11_09

//Khai báo biến toàn cục: i

int i;

int main()
{
    F[1]=1; F[2]=1;
    for (int i=3;i<=6;++i)
        F[i]=F[i-1]+F[i-2];
    cout<<F[6];    
    return 0;
}
 

 

Trong cách 1, ta viết một hàm đệ quy F(i) để tính số Fibonacci thứ i. Chương trình chính gọi F(6), nó sẽ gọi tiếp F(5) và F(4) để tính … Quá trình tính toán có thể vẽ như cây dưới đây. Ta nhận thấy để tính F(6) nó phải tính 1 lần F(5), 2 lần F(4), 3 lần F(3), 5 lần F(2), 3 lần F(1).

 

 

tinhoche11_012

 

Cách 2 thì không như vậy. Trước hết nó tính sẵn F[1] và F[2], từ đó tính tiếp F[3], lại tính tiếp được F[4], F[5], F[6]. Đảm bào rằng mỗi giá trị Fibonnaci chỉ phải tính 1 lần.

 

(Cách 2 còn có thể cải tiến thêm nữa, chỉ cần dùng 3 biến tính lại giá trị lẫn nhau).

tinhoche11_04Trước khi áp dụng phương pháp quy hoạch động ta phải xét xem phương pháp đó có thỏa mãn những yêu cầu dưới đây hay không:
+Bài toán lớn phải phân rã được thành nhiều bài toán con, mà sự phối hợp lời giải của các bài toán con đó cho ta lời giải của bài toán lớn.
+Vì quy hoạch động là đi giải tất cả các bài toán con, nên nếu không đủ không gian vật lý lưu trữ lời giải (bộ nhớ, đĩa,…) để phối hợp chúng thì phương pháp quy hoạch động cũng không thể thực hiện được.
+Quá trình từ bài toán cơ sở tìm ra lời giải bài toán ban đầu phải qua hữu hạn bước.

Các khái niệm:
+Bài toán giải theo phương pháp quy hoạch động gọi là bài toán quy hoạch động.
+Công thức phối hợp nghiệm của các bài toán con để có nghiệm của bài toán lớn gọi là công thức truy hồi của quy hoạch động.
+Tập các bài toán nhỏ nhất có ngay lời giải để từ đó giải quyết các bài toán lớn hơn gọi là cơ sở quy hoạch động.
+Không gian lưu trữ lời giải các bài toán con để tìm cách phối hợp chúng gọi là bảng phương án của quy hoạch động.

Các bước cài đặt một chương trình sử dụng quy hoạch động: (Nhớ kỹ)
+Giải tất cả các bài toán cơ sở (thông thường rất dễ), lưu các lời giải vào bảng phương án.
+Dùng công thức truy hồi phối hợp những lời giải của các bài toán nhỏ đã lưu trong bảng phương án để tìm lời giải của những bài toán lớn hơn và lưu chúng vào bảng phương án. Cho tới khi bài toán ban đầu tìm được lời giải.
+Dựa vào bảng phương án, truy vết tìm ra nghiệm tối ưu.

tinhoche11_01Cho đến nay, vẫn chưa có một định lý nào cho biết một cách chính xác những bài toán nào có thể giải quyết hiệu quả bằng quy hoạch động. Tuy nhiên để biết được bài toán có thể giải bằng quy hoạch động hay không, ta có thể tự đặt câu hỏi : “Một nghiệm tối ưu của bài toán lớn có phải là sự phối hợp các nghiệm tối ưu của các bài toán con hay không?”“Liệu có thể nào lưu trữ được nghiệm các bài toán con dưới một hình thức nào đó để phối hợp tìm được nghiệm bài toán lớn”.

Cuối cùng trước khi khảo sát một số bài toán quy hoạch động, ta nhắc lại: Phương pháp tốt nhất để giải quyết mọi bài toán trong tin học là biết sử dụng và phối hợp uyển chuyển nhiều thuật toán, không được lạm dụng hay coi thường bất cứ một phương pháp nào./.