Đề tài của em là tìm hiểu về phương pháp quy hoạch động, tư tưởng cơ bản của phương pháp này là: Để giải một bài toán ta chia bài toán đó thành các bài toán nhỏ hơn có thể giải một cách
Trang 1LỜI NÓI ĐẦU
Trong quá trình học tập, chúng ta gặp rất nhiều các bài tập về Toán-Tin Các bài tập dạng này rất phong phú và đa dạng Thực tế chưa có thuật toán hoàn chỉnh có thể áp dụng cho mọi bài toán Tuy nhiên người ta đã tìm ra một số thuật toán chung như chia để trị, tham ăn, quay lui, Các thuật toán này có thể
áp dụng để giải một lớp khá rộng các bài toán hay gặp trong thực tế
Đề tài của em là tìm hiểu về phương pháp quy hoạch động, tư tưởng cơ bản của phương pháp này là: Để giải một bài toán ta chia bài toán đó thành các bài toán nhỏ hơn có thể giải một cách dễ dàng Sau đó kết hợp lời giải các bài toán con, ta có được lời giải bài toán ban đầu Trong quá trình giải các bài toán con đôi khi ta gặp rất nhiều kết quả trùng lặp của các bài toán con Để tăng tính hiệu quả, thay vì phải tính lại các kết quả đó, ta lưu chúng vào một bảng Khi cần lời giải của một bài toán con nào đó ta chỉ cần tìm trong bảng, không cần tính lại
Cùng với sự chỉ bảo tận tình của cô Hoàng Thị Kim Ngân em đã hoàn
thành báo cáo này Trong báo cáo không tránh khỏi những sai xót mong thầy,
cô và các bạn góp ý để bản báo cáo được hoàn thiện hơn
Trang 2CHƯƠNG I: LÝ THUYẾT
Tư tưởng của thuật toán quy hoạch động khá đơn giản Tuy nhiên khi áp dụng thuật toán vào trường hợp cụ thể lại không dễ dàng Khi giải bài toán bằng phương pháp này, chúng ta phải thực hiện hai yêu cầu quan trọng sau:
- Tìm công thức truy hồi xác định nghiệm bài toán qua nghiệm các bài toán con nhỏ hơn
- Với mỗi bài toán cụ thể, ta đề ra phương án lưu trữ nghiệm một cách hợp
lý để từ đó có thể truy cập một cách thuận tiện nhất
I- Công thức truy hồi
1- Ví dụ
Cho số tự nhiên n ≤ 100 Hãy cho biết có bao nhiêu cách phân tích số n thành tổng của dãy các số nguyên dương, các cách phân tích là hoán vị của nhau chỉ tính là một cách.
Trang 3Các cách phân tích số v thành tổng các số nguyên dương ≤ m có thể chia làm hai loại:
- Loại 1: Không chứa số m trong phép phân tích, khi đó số cách phân tích loại này chính là số cách phân tích số v thành tổng các số nguyên dương
< m, tức là số cách phân tích số v thành tổng các số nguyên dương ≤ m - 1 và bằng F[m - 1,v]
- Loại 2: Có chứa ít nhất một số m trong phép phân tích Khi đó nếu trong các cách phân tích loại này ta bỏ đi số m đó thì ta sẽ được các cách phân tích số v – m thành tổng các số nguyên dương ≤ m (Lưu ý: điều này chỉ đúng khi không tính lặp lại các hoán vị của một cách) Có nghĩa là về mặt số lượng,
số các cách phân tích loại này bằng F[m,v – m]
Trong trường hợp m > v thì rõ ràng chỉ có các cách phân tích loại 1, còn trong trường hợp m ≤ v thì sẽ có cả các cách phân tích loại 1 và loại 2 Vì thế:
Ta có công thức xây dựng F[m,v] từ F[m - 1,v] và F[m,v - m] Công thức
này có tên gọi là công thức truy hồi đưa việc tính F[m,v] về việc tính các
F[m’,v’] với dữ liệu nhỏ hơn Tất nhiên cuối cùng ta sẽ quan tâm đến F[n,n]: Số các cách phân tích n thành tổng các số nguyên dương ≤ n.
Ví dụ với n = 5, bảng F sẽ là:
Trang 4Nhìn vào bảng F, ta thấy rằng F[m,v] được tính bằng tổng của:
Một phần tử ở hàng trên: F[m -1,v] và một phần tử ở cùng hàng, bên trái: F[m,v - m]
Ví dụ F[5,5] sẽ được tính bẳng F[4,5] + F[5,0], hay F[3,5] sẽ được tính bằng F[2,5] + F[3,2] Chính vì vậy để tính F[m,v] thì F[m – 1,v] và F[m,v - m] phải được xác định trước Suy ra thứ tự hợp lý để tính các phần tử trong bảng F
sẽ phải là theo thứ tự từ trên xuống và trên mỗi hàng thì tính theo thứ tự từ trái qua phải
Điều đó có nghĩa là ban đầu ta phải tính hàng 0 của bảng: F[0,v] = số dãy
có các phần tử ≤ 0 mà tổng bằng v, theo quy ước ở đề bài thì F[0,0] = 1 còn F[0,v] với mọi v > 0 đều là 0
Vậy giải thuật dựng rất đơn giản: khởi tạo dòng 0 của bảng F: F[0,0] = 1 còn F[0,v] với mọi v > 0 đều bằng 0, sau đó dùng công thức truy hồi tính ra tất
cả các phần tử của bảng F Cuối cùng F[n,n] là số cách phân tích cần tìm
2- Cải tiến thứ nhất
Cách làm trên có thể tóm tắt lại như sau: Khởi tạo dòng 0 của bảng, sau đó dùng dòng 0 tính dòng 1, dùng dòng 1 tính dòng 2 v.v… tới khi tính được hết dòng n Có thể nhận thấy rằng khi đã tính xong dòng thứ k thì việc lưu trữ các dòng từ dòng 0 tới dòng k – 1 là không cần thiết bởi vì việc tính dòng k + 1 chỉ phụ thuộc các giá trị lưu trữ trên dòng k Vậy ta có thể dùng hai mảng một chiều: Mảng Current lưu dòng hiện thời đang xét của bảng và mảng Next lưu dòng kế tiếp, đầu tiên mảng Current được gán các giá trị tương ứng trên dòng 0 Sau đó dùng mảng Current tính mảng Next, mảng Next sau khi tính sẽ mang các giá trị tương ứng trên dòng 1 Rồi lại gán mảng Current:= Next và tiếp tục dùng mảng Current tính mảng Next, mảng Next sẽ gồm các giá trị tương ứng trên dòng 2 v.v
Cách làm trên đã tiết kiệm được khá nhiều không gian lưu trữ, nhưng nó hơi chậm hơn phương pháp đầu tiên vì phép gán mảng (Current:= Next) Có thể cải tiến thêm cách làm này
Trang 53- Cải tiến thứ hai
Ta vẫn còn cách tốt hơn nữa, tại mỗi bước, ta chỉ cần lưu lại một dòng của bảng F bằng một mảng 1 chiều, sau đó dùng mảng đó tính lại chính nó để sau khi tính, mảng một chiều sẽ lưu các giá trị của bảng F trên dòng kế tiếp
II- Phương pháp quy hoạch động
1- Bài toán quy hoạch
Bài toán quy hoạch là bài toán tối ưu: gồm có một hàm f gọi là hàm mục tiêu hay hàm đánh giá, các hàm g1, g2, …, gn cho giá trị logic gọi là hàm ràng buộc Yêu cầu của bài toán là tìm một cấu hình x thỏa mãn tất cả các ràng buộc
g1, g2, …, gn: gi(x) = TRUE (∀i: 1 ≤ i ≤ n) và x là tốt nhất, theo nghĩa không tồn tại một cấu hình y nào khác thỏa mãn các hàm ràng buộc mà f(y) tốt hơn f(x)
Các dạng bài toán quy hoạch rất phong phú và đa dạng, ứng dụng nhiều trong thực tế, nhưng cũng cần biết rằng, đa số các bài toán quy hoạch là không giải được, hoặc chưa giải được Cho đến nay, người ta mới chỉ có thuật toán đơn hình giải bài toán quy hoạch tuyến tính lồi, và một vài thuật toán khác áp dụng cho các lớp bài toán cụ thể
2- 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ó bản 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 chúng ta đã tìm hiểu nguyên lý chia để trị 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ó làm 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 quyết những bài 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
Trang 6khác nhau giữa Quy hoạch động và phép phân giải đệ quy và cũng là nội dung phương pháp quy hoạch động:
- Phép phân giải đệ 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 nhỏ hơn và lại đi giải tiếp 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)
Phương pháp quy hoạch động dùng kỹ thuật bttom up (đi từ dưới lên):Xuất phát từ các trường hợp riêng đơn giản nhất, có thể tìm ngay ra nghiệm bằng cách kết hợp nghiệm của chúng, ta nhận được nghiệm của bài toán cỡ lớn hơn Cứ thế tiếp tục, chúng ta sẽ nhận được nghiệm của bài toán Trong quá trình đi từ dưới lên chúng ta sẽ sử dụng một bảng để lưu giữ lời giải của các bài toán con đã giải, không cần quan tâm đến nó được sử dụng ở đâu sau này
Khi giải một bài toán con, cần đến nghiệm của bài toán con nhỏ hơn, ta chỉ cần tìm kiếm trong bảng, không cần phải giải lại Chính vì thế mà giải thuật nhận được bằng phương pháp này rất có hiệu quả
Trướ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:
Trang 7- 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 (hay phương trình truy toán) 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 hoach động
Cho đế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?” và “Liệu có thể 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”
- Ưu điểm của phương pháp quy hoạch động: chương trình chạy nhanh
- Phạm vi áp dụng của phương pháp quy hoạch động
Các bài toán tối ưu: như tìm xâu con chung dài nhất, bài toán ba lô, tìm đường đi ngắn nhất, bài toán otomat với số phép biến đổi ít nhất, …
Các bài toán có công thức truy hồi
- Hạn chế của phương pháp quy hoạch động:
Phương pháp quy hoạch động không đem lại hiệu quả trong các trường hợp sau:
+ Sự kết hợp lời giải của các bài toán con chưa chắc cho ta lời giải của bài toán lớn
+ Số lượng các bài toán con cần giải quyết và lưu trữ kết quả có thể rất lớn, không thể chấp nhận được
+ Không tìm được công thức truy hồi
Trang 8CHƯƠNG II MỘT SỐ BÀI TOÁN QUY HOẠCH ĐỘNG
1- Bài toán cái túi
Trong siêu thị có n gói hàng (n ≤ 100), gói hàng thứ i có trọng lượng là W[i]≤ 100 và trị giá V[i] ≤ 100 Một tên trộm đột nhập vào siêu thị, tên trộm mang theo một cái túi có thể mang được tối đa trọng lượng M (M≤100) Hỏi tên trộm sẽ lấy đi những gói hàng nào để được tổng giá trị lớn nhất
Input: file văn bản BAG.INP
• Dòng 1: Chứa hai số n, M cách nhau ít nhất một dấu cách
• n dòng tiếp theo, dòng thứ i chứa hai số nguyên dương Wi, Vi cách nhau
ít nhất một dấu cách
Output: file văn bản BAG.OUT
• Dòng 1: Ghi giá trị lớn nhất tên trộm có thể lấy
• Dòng 2: Ghi chỉ số những gói bị lấy
Cách giải:
Nếu gọi F[i, j] là giá trị lớn nhất có thể có bằng cách chọn trong các gói
{1, 2, …, i} với giới hạn trọng lượng j Thì giá trị lớn nhất khi được chọn trong
số n gói với giới hạn trọng lượng M chính là F[n, M]
a Công thức truy hồi tính F[i, j].
Với giới hạn trọng lượng j, việc chọn tối ưu trong số các gói {1, 2, …,i – 1, i} để có giá trị lớn nhất sẽ có hai khả năng:
Trang 9• Nếu không chọn gói thứ i thì F[i, j] là giá trị lớn nhất có thể bằng cách chọn trong số các gói {1, 2, …, i – 1} với giới hạn trọng lượng là j Tức là
F[i, j] = F[i - 1, j]
• Nếu có chọn gói thứ i (tất nhiên chỉ xét tới trường hợp này khi mà Wi ≤ j) thì F[i, j] bằng giá trị gói thứ i là Vi cộng với giá trị lớn nhất có thể có được bằng cách chọn trong số các gói {1, 2, …, i – 1} với giới hạn trọng lượng j –
Wi Tức là về mặt giá trị thu được:
F[i, j] = Vi + F[i - 1, j - Wi]
Vì theo cách xây dựng F[i, j] là giá trị lớn nhất có thể, nên F[i, j] sẽ là max trong 2 giá trị thu được ở trên
b Cơ sở quy hoạch động:
Dễ thấy F[0, j] = giá trị lớn nhất có thể bằng cách chọn trong số 0 gói = 0
CODE:
Trang 10{Sau đó đánh giá: nếu chọn gói thứ i sẽ được lợi hơn thì đặt lại F[i, j]}
if (j >= W[i]) and (F[i, j] < F[i - 1, j - W[i]] + V[i]) then
F[i, j] := F[i - 1, j - W[i]] + V[i];
end;
Trang 11procedure Trace; {Truy vết tìm nghiệm tối ưu}
begin
WriteLn(F[n, M]); {In ra giá trị lớn nhất có thể kiếm được}
while n <> 0 do {Truy vết trên bảng phương án từ hàng n lên hàng 0} begin
if F[n, M] <> F[n - 1, M] then {Nếu có chọn gói thứ n}
{Định nghĩa lại thiết bị nhập/xuất chuẩn}
Assign(Input, 'BAG.INP'); Reset(Input);
Assign(Output, 'BAG.OUT'); Rewrite(Output);
2- Bài toán đổi tiền
Cho n loại tờ giấy bạc Tờ giấy bạc thứ i có mệnh giá A[i] Số tờ mỗi loại không giới hạn Cần chi trả cho khách hàng số tiền M đồng Hãy cho biết mỗi loại tiền cần bao nhiêu tờ sao cho tổng số tờ là ít nhất Nếu không đổi được thì thông báo “KHONG DOI DUOC” N < 50; A[i] < 256; M < 10000
Trang 12Xếp mệnh giá A[i] tăng dần.
Khởi gán Fx[i] = ∞, X[i] = 0 ∀j = 1 M
Gán Fx[0] = 0
Với số tiền i chạy từ 1 đến M, ta tính Fx[i] và X[i] bằng cách:
Nếu chọn loại tiền j thì số tiền còn lại là i – A[j]
Fx[i] = Min(F[i – A[j]] + 1) nếu i >= A[j]
Min xét với loại tiền j chạy từ 1 đến n
X[i] = j ứng với giá trị min của Fx[i]
Dưới đây là mảng Fx[i] và X[i] tính được trong ví dụ trên
(dùng 3 loại tiền 3 đồng, 10 đồng, 12 đồng để đổi số tiền 18 đồng
Procedure TaoBang;
Var i: Word;
J: Byte;
Begin
Trang 13For i:=1 to M do Fx[i]:= VoCuc; {VoCuc = MaxInt – 1}
Fx[0]:=0;
FillChar (X, Sizeof(x), 0);
For i:=1 to M do {i là số tiền}
For j:=n downto 1 do {j là loại tiền}
3- Bài toán đường đi của robot tạo thành số nhị phân lớn nhất
Cho một bảng ô vuông m dòng, n cột (2<=n,m<=30) các ô ghi các số là 0 hoặc 1 Tìm đường đi của robot, từ góc trái trên (ô (1,1)) xuống góc phải (ô (m, n)) dưới theo nguyên tắc chỉ được dịch chuyển sang phải và xuống dưới sao cho các số trên đường đi tạo thành một số nhị phân có giá trị lớn nhất
Dữ liệu vào: ghi trong tệp tin văn bản Robot.inp gồm
- Dòng đầu tiên ghi giá trị m và n
- M dòng tiếp theo, trên mỗi dòng ghi n số 0 hoặc 1 các số này cách nhau ít nhất 1 khoảng trống
Dữ liệu ra: Ghi vào tập tin văn bản robot.out gồm
- Dòng đầu tiền ghi giá trị thập phân của số nhị phân được tạo thành ở trên
- Các dòng tiếp theo ghi tọa độ các bước đi (dòng ghi trước, cột ghi sau)
Trang 14a Công thức truy hồi:
Gọi F[i,j] là giá trị thập phân của số nhị phân lớn nhất bằng cách đi từ ô (1,1) tới ô (i,j)
Khi thêm một chữ số 0 hoặc 1 vào cuối một số nhị phân thì ta sẽ được giá trị mới là:
Trang 15c Truy vết
Bằng thủ tục đệ quy: Bắt đầu từ ô (m,n), quá trình truy vết kết thúc khi
ta truy đến đến ô (1,1) và ra giá trị F[m,n], tại mỗi bước truy vết ta sẽ truy về ô
có giá trị lớn hơn trong 2 ô: (m-1,n) và (m,n-1)
Cài đặt bằng ngôn ngữ Pascal:
Trang 18Em xin chân thành cảm ơn cô Hoàng Thị Kim Ngân là giáo viên trực tiếp
hướng dẫn em làm đề tài cùng toàn thể các cô giáo bộ môn đã tận tình chỉ bảo, hướng dẫn và giúp đỡ em hoàn thành đề tài thực tập này
Em xin chân thành cảm ơn!
Trang 19TÀI LIỆU THAM KHẢO
http://quyhoachdong.jimdo.com/
http://www.ddth.com/
http://www.vn-zoom.com/
http://kithuatlaptrinh.tk
Trang 20NHẬN XÉT CỦA GIÁO VIÊN