3. Một số ví dụ minh họa
3.2. Trở lại bài toán mảng con trọng số lớn nhất
Bài toán 3.2. Trong chương 2 ta đã trình bày thuật toán chia để trị để giải bài toán tìm dãy con
(mảng con) có trọng số nhất với thời gian tính cỡ O(nlog2n). Bây giờ ta xét cách tiếp cận bằng quy hoạch động để giải bài toán này.
a) Các bước qui hoạch động
Bước 1: Nêu giả thiết hàm qui hoạch động. Gọi s(i) là tổng của dãy con lớn nhất trong dãy:
a1, a2, …., ai, i = 1,2,…, n. Rõ ràng s(n) là giá trị cần tìm.
Bước 2: Giải các bài toán đơn giản Hiển nhiên ta có s(1) = a1.
Bước 3: Xây dựng công thức qui hoạch động
Giả sử i > 1 và s(k) đã biết với k = 1,2,…, i - 1. Ta cần tính s(i) là tổng của dãy con lớn nhất của dãy con lớn nhất của dãy a1, a2, …, ai-1, ai.
Rõ ràng dãy con lớn nhất của dãy này hoặc là có chứa phần tử ai hoặc là không chứa phần tử ai, vì thế chỉ có thể là một trong hai dãy sau đây:
• Dãy con lớn nhất của dãy a1, a2, …, ai-1.
• Dãy con lớn nhất của dãy a1, a2, …, ai kết thúc tại ai. Từ đó suy ra
s(i) = max {s(i-1), e(i)},
Trong đó e(i) là tổng của dãy con lớn nhất của dãy a1, a2, …, ai kết thúc tại ai. Lưu ý rằng để tính e(i), i = 1, 2, …, n, ta cũng có thể sử dụng công thức đệ quy sau: e(1) = a1;
e(i) = max {ai, e(i-1) + ai }, i > 1.
b) Mô phỏng Pascal
Ta có thuật toán sau để giải bài toán đặt ra:
procedure Maxsub(a);
begin
e := a[1]; (* e là tổng của dãy con lớn nhất *) s[1] := a[1]; (* s là mảng qui hoạch động*)
imax : = 1; (* imax là vị trí kết thúc của dãy con lớn nhất *) for i: = 2 to n do begin u := e + a[i]; v := a[i]; if (u > v) then e := u else e := v; if (e > s[i-1]) then begin s[i] = e; imax: = i; end
else s[i] := s[i-1] end;
end;
Dễ thấy thuật toán Maxsub có thời gian tính là O(n).