MỘT SỐ ĐỊNH HƯỚNG CHO VIỆC ĐỊNH NGHĨA BÀI TOÁN CON VÀ XÁC ĐỊNH CẤU TRÚC CON TỐI ƯU TRONG QUÁ TRÌNH GIẢI CÁC BÀI TOÁN BẰNG PHƯƠNG PHÁP QUY HOẠCH ĐỘNG Nguyễn Văn Minh Trường PTTH Chuyên Lê
Trang 1MỘT SỐ ĐỊNH HƯỚNG CHO VIỆC ĐỊNH NGHĨA BÀI TOÁN CON VÀ XÁC ĐỊNH CẤU TRÚC CON TỐI ƯU TRONG QUÁ TRÌNH GIẢI CÁC BÀI TOÁN
BẰNG PHƯƠNG PHÁP QUY HOẠCH ĐỘNG
Nguyễn Văn Minh
Trường PTTH Chuyên Lê Quý Đôn - Quảng Trị.
Làm sao cho học sinh PTTH có thể tiếp cận được lời giải của bài toán cùng với
kỹ thuật lập trình đặc trưng của phương pháp quy hoạch động là trăn trở của rất nhiều giáo viên trong quá trình giảng dạy phương pháp này
Tìm ra các bài toán con phù hợp cho một bài toán khi giải là một công việc phụ thuộc rất nhiều kinh nghiệm và sự sáng tạo của người giải Tuy nhiên, cũng có một
số định nghĩa lặp lại trong các bài toán quy hoạch động Bài viết đề cập đến bốn định hướng cho việc định nghĩa bài toán con và xác định cấu trúc con tối ưu trên các định nghĩa đó
I MỞ ĐẦU.
Phương pháp quy hoạch động thường dùng để giải các bài toán tối ưu có bản chất đệ quy, tức là việc tìm lời giải tối ưu cho bài toán đó có thể đưa về việc tìm lời giải tối ưu của một số hữu hạn các bài toán con
Thông thường khi giải một bài toán bằng phương pháp quy hoạch động chúng ta cần thực hiện 4 bước sau:
1 Xác định cấu trúc của một lời giải tối ưu
Tìm cách chia bài toán thành các bài toán con
Xác định cấu trúc con tối ưu, tức là lời giải tối ưu của các bài toán con sẽ đem lại lời giải tối ưu cho bài toán ban đầu
2 Định nghĩa đệ quy cho giá trị của một lời giải tối ưu dựa trên giá trị có được từ các bài toán con
3 Tính giá trị của một lời giải tối ưu từ dưới lên
Tính giá trị của một lời giải tối ưu, xuất phát từ bài toán con nhỏ nhất và lưu các giá trị đó lại theo một cách nào đó
Ở bước sau sẽ dùng các giá trị đã lưu từ các bước trước
4 Xây dựng lời giải tối ưu từ các thông tin đã được lưu lại
Bài viết xin phép trao đổi một số vấn đề liên quan đến bước 1 và 2 nêu trên, đó cũng là các bước quyết định cho việc giải hoàn chỉnh một bài toán quy hoạch động
Có nhiều định hướng khác nhau cho việc định nghĩa các bài toán con, từ đó cho phép chúng ta xác định cấu trúc con tối ưu của bài toán Bốn định hướng sau cho phép chúng ta tiếp cận 4 lớp bài toán phổ biến có thể giải bằng phương pháp quy hoạch động
II ĐỊNH NGHĨA CÁC BÀI TOÁN CON VÀ XÁC ĐỊNH CẤU TRÚC CON TỐI ƯU.
II 1 Dạng tiền tố (hậu tố).
Trang 2Định nghĩa bài toán con.
Bài toán ở dạng này với đầu vào (input) thường là một dãy gồm n thành phần x1,
x2, …, xn Khi đó việc phân chia bài toán thành các bài toán con ở dạng tiền tố là:
x1, x2, …, xi, với i ≤ n Các bài toán con ở dạng hậu tố là: xi, x2, …, xn, với i ≥ 1 Khi
phân chia bài toán ban đầu thành các bài toán con ở dạng tiền tố ta có mô hình như sau:
BT con thứ
Hình 1: Mô hình dạng tiền tố.
Cấu trúc con tối ưu:
Trường hợp 1: Cấu trúc con tối ưu của mỗi bài toán con phụ thuộc một số bài
toán con được xác định (không cần phải tìm kiếm) Cấu trúc đệ quy dạng này hoặc nhị phân, hoặc tam phân, …
Bài toán 1: Cho dãy số nguyên dương a1, a2, …an Hãy chọn một số số hạng của dãy nhưng không được chọn 3 số hạng liền nhau, sao cho tổng giá trị các số hạng được chọn là lớn nhất
Ví dụ: A = (6, 10, 13, 9, 8, 1), có thể chọn (6, 13, 9, 1) cách chọn này có tổng giá trị 29, có thể chọn (6, 10, 9, 8) cách chọn này có tổng giá trị là 33 là cách chọn có
tổng giá trị lớn nhất
1 Bài toán con thứ i gồm các thành phần tứ 1 đến i Có thể phát biểu lại bài toán như sau: Hãy chọn trong các số hạng từ 1 đến i, nhưng không được chọn 3 số hạng
liền nhau, sao cho tổng giá trị các số hạng được chọn là lớn nhất Bài toán con thứ
n là bài toán ban đầu.
2 Với cách chia đó ta có:
+ Với bài toán con 1, chỉ có 1 món quà nên tổng giá trị thu được là a1, giá trị tối
ưu cho bài toán này là a1.
+ Với bài toán con 2 cũng vậy, chỉ có 2 món quà nên tổng giá trị thu được là
a1+a2, giá trị tối ưu cho bài toán này là a1+a2
+ Với bài toán con 3 thì sẽ có các cách chọn thỏa mãn yêu cầu của bài toán: (a1,
a2), (a1, a3), (a2, a3) với tổng giá trị lần lượt là: a1+a2, a1+a3, a2+a3 Từ đó giá trị tối
ưu cho bài toán này là giá trị lớn nhất trong 3 cách chọn: max{a1+a2, a1+a3, a2+a3} + Với bài toán con 4 ta có các cách chọn: (a1, a2), (a1, a3), (a1, a4), (a2, a3), (a2,
a4), (a3, a4), (a1, a2, a4), (a1, a3, a4) Từ đó giá trị tối ưu cho bài toán này là:
max{a1+a2, a1+a3, a1+a4, a2+a3, a2+a4, a3+a4, a1+a2+a4, a1+a3+a4}
= max{max{a1+a2, a1+a3, a2+a3}, max{a1+a4, a2+a4, a1+a2+a4}, max{a1+a3+a4, a3+a4}}.
= max{max{a1+a2, a1+a3, a2+a3}, (a1+a2)+a4 , (a1)+a3 +a4}.
BT con 3 BT con 2 BT con 1
(Do a1, a2, a3, a4 nguyên dương nên: max{a1+a4, a2+a4, a1+a2+a4} = a1+a2+a4 và
max{a1+a3+a4, a3+a4} = a1+a3+a4)
Trang 3Có thể thấy lời giải tối ưu của bài toán con thứ tư phụ thuộc lời giải tối ưu của các bài toán con 1, 2 và 3 Hay bài toán có cấu trúc con tối ưu: lời giải tối ưu của 3
bài toán con thứ i-1, i-2 và i-3 sẽ cho lời giải tối ưu cho bài toán con thứ i, lời giải tối ưu của 3 bài toán con thứ n-1, n-2 và n-3 sẽ cho lời giải tối ưu cho bài toán con thứ n – bài toán ban đầu.
Gọi f(i) là giá trị tối ưu của bài toán con thứ i, là tổng giá trị lớn nhất có thể chọn được trong các món quà từ món quà thứ nhất đến món quà thứ i Ta có:
f(1)=a 1
f(2)=a 1 +a 2
f(3)=max{a 1 +a 2 , a 1 +a 3 , a 2 +a 3 }
f(4)=max{max{a 1 +a 2 , a 1 +a 3 , a 2 +a 3 }, (a 1 +a 2 +a 4 ), (a 1 )+a 3 +a 4 }
=max{f(3), f(2)+a 4 , f(1))+a 3 +a 4 }.
…
f(i)=max{f(i-1), f(i-2)+a i , f(i-3)+a i-1 +a i }.
Từ đó ta có công thức:
Gọi mãng a[1 N] lưu dãy đầu vào (input) Ta có đoạn chương trình đệ quy tính giá trị tối ưu f(n) cho bài toán.
function f(i : longint) : longint;
begin
if i = 1 then f a[1] ≔ a[1]
else if i = 2 then f ≔ a[1] a[1] + a[2]
else if i = 3 then f ≔ a[1] max(a[1] + a[2], a[1] + a[3], a[2] + a[3])
else f := max(f(i - 1), f(i - 2) + a[i], f(i - 3) + a[i - 1] + a[i]);
end;
BEGIN
…
write(f(n));
…
END.
Trường hợp 2: Cấu trúc con tối ưu của mỗi bài toán con phụ thuộc một số bài
toán con được chưa được xác định (cần phải tìm kiếm) Cấu trúc đệ quy của bài toán thường ở dạng tuyến tính
Bài toán 2 : Dãy con đơn điệu tăng dài nhất.
Cho dãy số nguyên A, a1, a2, …, an Một dãy con của dãy A là dãy thu được bằng cách chọn ra từ A một số phần tử và giữ nguyên thứ tự của chúng.
Hãy tìm dãy con đơn điệu tăng của A có độ dài lớn nhất bắt đầu từ a1
Ví dụ: với A = (5, 2, 8, 6, 3, 6, 9, 7) thì (2, 3, 6, 9) là một dãy con đơn điệu tăng dài nhất của A.
1 Bài toán con thứ i gồm các phần tử từ 1 đến i của dãy A Có thể phát biểu lại bài
toán như sau: Hãy tìm dãy con đơn điệu dài nhất của dãy gồm các phần tử từ 1 đến
i Bài toán con thứ n là bài toán ban đầu
2 Với cách phân chia đó ta có:
Trang 4+ Với bài toán con thứ nhất, bởi chỉ có 1 phần tử a 1 nên nó là dãy đơn điệu tăng
độ dài (lớn nhất) là 1
+ Khi xét bài toán con thứ i, ta cần xem phần tử aj của các bài toán con j từ 1 đến i-1 xem chúng có thỏa mãn aj < ai không? Điều này đảm bảo cho ta có thể
ghép thêm ai vào cuối các dãy con đơn điệu tăng kết thúc tại j của bài toán con j.
Trong trường hợp có nhiều dãy con (của các bài toán con) như vậy chúng ta chọn dãy con nào là dài nhất nhằm bảo đảm tính dài nhất của bài toán
Đó cũng chính là cấu trúc con tối ưu của bài toán: lời giải tối ưu của bài toán
con thứ i phụ thuộc vào lời giải tối ưu của các bài toán con trong số các bài toán con từ bài toán con j (1 ≤ j ≤ i - 1) mà aj < ai
Từ phân tích trên, nếu gọi f(i) là giá trị tối ưu của bài toán con thứ i, tức là độ dài của dãy con đơn điệu tăng có được từ dãy gồm các phần tử từ a1 đến ai thì:
f(i) = max{f(j)+1| 1 ≤ j < i và aj < a i }.
Từ đó ta có công thức sau:
Gọi mãng a[1 N] lưu dãy đầu vào, để đơn giản và thấy rõ hơn cấu trúc con tối
ưu của bài ta thiết kế chương trình con đệ quy chỉ tính giá trị tối ưu của bài toán
con thứ i: f(i) Việc cập nhật giá trị tối ưu cho bài toán ban đầu: max{f(i)|i = 1, 2,
…, N} được thực hiện tách rời.
function f(i : longint) : longint;
var j, tmp : longint;
begin
if i = 1 then f 1 ≔ a[1]
else begin
tmp 1 ≔ a[1]
for j := 1 to i – 1 do
if a[j] < a[i] then tmp := max(tmp, f(j) + 1);
f tmp; ≔ a[1]
end;
end;
BEGIN
…
MaxLenSeq ≔ a[1] 0;
for i ≔ a[1] 1 to N do begin
tmp ≔ f(i);
if MaxLenSeq < tmp then MaxLenSeq ≔ a[1] tmp;
end;
write(MaxLenSeq);
…
END.
II 2 Dạng hai hay nhiều tiền tố (hậu tố).
Bài toán ở dạng này với đầu vào (input) thường là hai hay nhiều dãy số thành
phần của mỗi dãy có thể khác nhau Ta xét 2 dãy sau X = x1, x2, …, xn và Y = y1, y2,
…, ym khi đó mỗi bài toán con của dạng này là 2 tiền tố của X và Y x1, x2, …, xi, với
i ≤ n và y1, y2, …, yj, với j ≤ m Khi phân chia bài toán ban đầu thành các bài toán
con ở dạng tiền tố ta có mô hình như sau:
Trang 5y1 y 2 y 3 y i ym
BT con (1, 1)
BT con (i, j)
BT con (n, m)
Hình 2: Mô hình bài toán con
Cấu trúc con tối ưu: tương ứng với quan hệ giữa 2 tiền tố Thông thường là một
số bài toán con xác định
Bài toán 3: Dãy con chung dài nhất (LCS).
Cho X = x1, x2, …, xm và Y = y1, y2, …, yn Hãy tìm dãy con chung Z của X và Y.
Ví dụ:
1 Bài toán con (i, j) là các tiền tố x1, x2, …, xi, với i ≤ m và y1, y2, …, yj, với j ≤ n của 2 dãy X và Y Có thể phát biểu lại bài toán như sau: Hãy tìm dãy con chung dài nhất của 2 dãy x1, x2, …, xi và y1, y2, …, yj
2 Với cách chia đó ta có
+ Với bài toán con (1, 1) nếu x1 = y1 thì độ dài dãy Z là 1, ngược lại là 0.
+ Với bài toán con (i, j) thì:
- nếu x1 = y1 thì độ dài dãy Z sẽ là độ dài dãy con chung dài nhất thu được từ
bài toán con (i – 1, j - 1) thêm một phần tử chung nữa
- nếu x1 ≠ y1 thì độ dài dãy Z, hoặc là độ dài dãy con chung dài nhất thu được
từ bài toán con (i – 1, j) hoặc là từ bài toán con (i, j - 1), dãy nào dài hơn thì chọn.
Gọi f(i, j) là giá trị tối ưu của bài toán con (i, j), ta có công thức sau:
Trang 6Gọi x[1 m], y[1 n] là 2 dãy đầu vào, đoạn chương trình đệ quy sau thực hiện tìm độ dài dãy con chung dài nhất của x và y.
function f(i, j : longint) : longint;
begin
if (i = 0) or (j = 0) then f ≔ a[1] 0
else if x[i] = y[j] then f ≔ a[1] f(i – 1, j – 1) + 1
else f := max(f(i, j - 1), f(i - 1, j));
end;
BEGIN
…
writeln(f(m, n));
…
END.
Bài toán 4: Bài toán đổi tiền.
Cho tập D gồm n loại tiền có mệnh giá d1, d2, …, dn, tìm cách đổi S đồng gồm các loại tiền trên sao cho số tờ tiền cần đổi là ít nhất Nghĩa là tìm tập K = (k1, k2,
…, kn (ki ≥ 0 với mọi i) sao cho k1d1 + k2d2 + … + kndn = S và tổng k1 + k2 + … + kn
nhỏ nhất Biết số loại tiền không hạn chế
Ví dụ: D = (1, 2, 4), S = 35 khi đó K = (1, 1, 8) Tổng số tờ tiền cần đổi là 10 tờ.
1 Xem X là tập D và Y tập gồm tất cả các số từ 1 đến S Bài toán con (i, j) là các tiền tố d1, d2, …, di, với i ≤ n và 0, 1, 2, …, j, với j ≤ S Có thể phát biểu lại bài toán như sau: Tìm cách đổi j đồng gồm các loại tiền d1, d2, …, di sao cho số tờ tiền
cần đổi là ít nhất Bài toán con (n, S) là bài toán ban đầu.
2 Với bài toán con (i, j):
+ các bài toán con (i, 0) có giá trị tối ưu là 0 với mọi i.
+ các bài toán con (1, j) mà j < d1 bởi không thể đổi nên giá trị tối ưu của bài toán con này ta quy ước là
+ các bài toán con (1, j) mà j > d1 thì ta có thể đổi và giá trị tối ưu của bài toán
con này tương ứng sẽ là giá trị tối ưu của bài toán con (1, j – d1) + 1
+ các bài toán con (i, j) mà j < di với mọi i = 2, 3, …, n; rõ ràng là không đổi
được khi đó giá trị tối ưu của (i, j) sẽ là giá trị tối ưu của bài toán con (i – 1, j).
+ trường hợp còn lại là ta có thể đổi, tuy nhiên ta có thể chọn việc đổi hay không
- nếu không dùng tờ tiền loại i để đổi thì giá trị tối ưu của (i, j) sẽ bằng giá trị tối ưu của bài toán con (i – 1, j).
- còn nếu dùng ít nhất một tờ loại i để đổi thì số tiền còn lại cần đổi là j – di
hay giá trị tối ưu của (i, j) sẽ bằng giá trị tối ưu (số tờ tiền ít nhất) của bài toán con (i, j – di) thêm một tờ (di)
Gọi f(i, j) là giá trị tối ưu của bài toán con (i, j), ta có công thức:
Gọi d[1 n] mãng lưu đầu vào, ta có đoạn chương trình đệ quy sau:
Trang 7const inf = maxlongint;
function f(i, j:integer): integer;
begin
if j = 0 then f :=0
else if (i = 1) and (j < d[1]) then f := inf
else if i = 1 then f := 1 + f(1, j - d[1])
else if j < d[i] then f := f(i - 1, j)
else f := min(f(i-1, j), 1 + f(i, j-d[i]));
end;
BEGIN
…
writeln(f(n, S));
…
END.
II 3 Dạng dãy con.
Định nghĩa bài toán con.
Bài toán ở dạng này với đầu vào là một dãy gồm n thành phần x 1 , x 2 , …, x n Khi
đó việc phân chia thành các bài toán con ở dạng dãy con là: x i , x 2 , …, x j , với 1 ≤ i <
j ≤ n.
x 1 x 2 x i x j x n-1 x n
Bài toán con (i, j)
Hình 3: Mô hình dạng dãy con.
Cấu trúc con tối ưu:
Trường hợp 1: Cấu trúc con tối ưu của mỗi bài toán con phụ thuộc một số bài
toán con được xác định (không cần phải tìm kiếm)
Bài toán 5: PalinDrome.
Dãy kí tự s được gọi là đối xứng (palindrome) nếu các phần tử cách đều đầu và cuối giống nhau Cho dãy s tạo bởi n kí tự gồm các chữ cái hoa và thường phân biệt và các chữ số Một dãy con của s là dãy thu được sau khi bỏ đi một số bất kỳ các ký tự của s và giữ nguyên thứ tự các ký tự còn lại Hãy tìm độ dài dãy con đối xứng dài nhất của s.
Ví dụ: với dãy s gồm 9 kí tự, s = 'baeadbadb' thì sau khi xoá các kí tự thứ 5, 7, 8
và 9 sẽ thu được dãy con đối xứng chiều dài 5 là baeab: baeadbadb baeab Có
thể có nhiều cách xoá Tuy nhiên độ dài dãy con đối xứng dài nhất là 5
1 Do tính đối xứng ta chọn cách chia theo dạng dãy con Với cách chia như vậy,
bài toán con (i, j) gồm các ký tự s i , s i+1 , …, s j Gọi f(i, j) là giá trị tối ưu của bài toán con này – độ dài của dãy con đối xứng dài nhất có thể trích ra từ dãy con s i , s i+1 , …,
s j Lời giải của bài toán ban đầu (1, n) là f(1, n).
2 Xét bài toán con (i, j) Ta có:
1 Nếu i > j, chỉ số đầu trái lớn hơn chỉ số đầu phải, ta quy ước đặt f(i, j)=0.
2 Nếu i = j thì f(i, i) = 1, dãy khảo sát chỉ chứa đúng 1 kí tự nên nó là đối xứng.
3 Nếu i < j và s i = s j thì f(i, j) = f(i + 1, j – 1) + 2 Vì hai kí tự đầu và cuối dãy
s i s j giống nhau nên chỉ cần xác định chiều dài của dãy con đối xứng dài nhất trong
Trang 8đoạn giữa là s i+1 s j–1 (bài toán con (i + 1, j – 1)) rồi cộng thêm 2 đơn vị ứng với hai
kí tự đầu và cuối dãy Hình 4
s 1 s 2 s i s i+1 s j-1 s j s n
Bài toán con (i+1, j-1)
s i = s j
Hình 4: Trường hợp s i = s j.
4 Nếu i < j và s i s j , tức là hai kí tự đầu và cuối của dãy con s i s j là khác
nhau thì ta khảo sát hai dãy con là s i s j–1 (bài toán con (i, j – 1)) và s i+1 s j (bài toán
con (i+1, j)) để lấy chiều dài của dãy con đối xứng dài nhất trong hai dãy này làm kết quả, hình 5: f(i, j) = max{f(i, j-1),f(i+1, j)}
s 1 s 2 s i-1 s i s j s j+1 s n
Bài toán con (i+1, j)
s i s j
s i+1 s j-1
Bài toán con (i, j-1)
Hình 5: Trường hợp s i ≠ s j.
Vậy lời giải tối ưu của bài toán con (i, j) phụ thuộc vào sự tối ưu của các bài toán con (i+1, j-1), (i, j-1) và (i+1, j) Lời giải tối ưu của bài toán ban đầu (1, n) phụ thuộc vào sự tối ưu của các bài toán con (2, n-1), (1, n-1) và (2, n).
Ta có công thức sau:
Ta có chương trình con đệ quy sau:
function f(i, j : longint) : longint;
begin
if i > j then f 0 ≔ a[1]
else if i = j then f 1 ≔ a[1]
else if s[i] = s[j] then f f(i + 1, j - 1) + 2 else f := max(f(i, j - 1), f(i + 1, j); ≔ a[1]
end;
BEGIN
…
write(f(1, n));
…
END.
Trường hợp 2: Cấu trúc con tối ưu của mỗi bài toán con phụ thuộc một số bài
toán con được chưa được xác định (cần phải tìm kiếm)
Bài toán 6: Stones.
Có N đống sỏi xếp thành 1 hàng, đống thứ i có a i viên sỏi Ta có thể ghép hai đống kề nhau thành một đống và mất một chi phí bằng tổng hai đống sỏi đó Hãy
tìm cách ghép N đống sỏi này thành một đống với chi phí nhỏ nhất.
Trang 9Ví dụ có 5 đống sỏi: n = 5, a i = (4, 1, 2, 7, 5).
3
19
Chi phí: 41.
Hình 6: Cách ghép 1.
2
19
Chi phí: 43.
Hình 7: Cách ghép 2.
Với cách ghép như hình 6, tổng chi phí 41 Hình 7, tổng chi phí 43
Bài toán là sự đặt dấu ưu tiên phép toán vào giữa các cặp toán hạng và việc thực hiện các phép toán trong dấu ưu tiên có chi phí tương ứng với giá trị của phép toán vừa thực hiện (bài toán nhân ma trận) Như ví dụ hình 6 là cách đặt sau:
((4+(1+2))+(7+5)), hình 7 là (((4+1)+2)+(7+5)) Nếu tìm tất cả các cách đặt móc
sẽ có 4n cách đặt móc (số Catalan thứ n) Một cách tiếp cận khác là ta sẽ chia bài toán bởi các điểm chia i dạng: (a 1 , a 2 , …, a i )(a i+1 , a i+2 , …, a n ) với 1 ≤ i ≤ n Khi đó
để tối ưu bài toán (a 1 , a 2 , …, a n ) ta cần tối ưu các bài toán (a 1 , a 2 , …, a i ) và (a i+1 ,
a i+2 , …, a n ).
Dễ thấy với điểm chia i ta sẽ có các bài toán con tương ứng (cùng kiểu) Nếu bài
toán chỉ gồm một đống, chi phí là 0 Nếu bài toán có 2 đống ta cũng có ngay kết quả Nếu bài toán có 3 đống thì ta có thể dựa trên bài toán 2 đống và 1 đống để tìm kết quả, tiếp tục quá trình như vậy cho đến khi có N đống
Bằng cách dùng điểm chia ta có thể liệt kê tất cả các cách ghép: (a 1 )( a 2 , …, a n ), (a 1 , a 2 )(a 3 , a 4 , …, a n ), (a 1 , a 2 , a 3 )(a 4 , a 5 , …, a n ), …, (a 1 , a 2 , …, a i-1 )(a n ) và tìm cách
tối ưu chúng
1 Do tính đối xứng của phép đặt móc nên ta chia bài toán theo mô hình trên, bài
toán con (i, j) gồm các đống sỏi a i , a i+1 , …, a j Bài toán (1, N) là bài toán ban đầu.
2 Với cách chia bài toán con như vậy ta thấy: lời giải tối ưu cho bài toán (i, j) là tìm cách ghép các đống sỏi từ đống thứ i tới đống thứ j với tổng chi phí nhỏ nhất.
Với mọi cách ghép thì phép ghép cuối cùng luôn có chi phí là a i , a i+1 , …, a j
Với điểm chia k (i ≤ k ≤ j), lời giải tối ưu của bài toán (i, j) phụ thuộc vào lời giải tối ưu của các bài toán con (i, k) và (k+1, j) Hay nói cách khác là sẽ phụ thuộc vào tất cả các bài toán con được tạo ra từ điểm chia k:
k = i (a i )( a i+1 , …, a j )
k = i+1 (a i , a i+1 )(a i+2 , a i+3 , …, a j )
k = j (a i , a i+1 , …, a j-1 )(a j ) Gọi f(i, j) là giá trị tối ưu của bài toán con (i, j), tương ứng là tổng chi phí nhỏ nhất để ghép các đống sỏi từ đống i đến đống j thành một đống.
Từ đó ta có công thức sau:
Trang 10Gọi sum[i] = a 1 +a 2 +…+a i Khi đó ta có a i , a i+1 , …, a j = sum[j]-sum[i-1] Ta có hàm đệ quy tính giá trị tối ưu của bài toán con (i, j) như sau:
function f(i, j : longint) : longint;
var k, tmp : longint;
begin
if i = j then f 0 ≔ a[1]
else begin
tmp maxlongint; ≔ a[1]
for k i to j – 1 do tmp := min(tmp, f(i, k) + f(k + 1, j) + (sum[j] – sum[i - 1])); ≔ a[1]
f tmp; ≔ a[1]
end;
end;
BEGIN
…
Sum[0] 0; ≔ a[1]
for i ≔ a[1] 1 to N do sum[i] sum[i - 1] + a[i]; ≔ a[1]
write(f(1, n));
…
END.
(Một số bài toán tìm đường đi ngắn nhất trên đồ thị có trọng số cũng có cách tiếp cận dạng này)
II 4 Dạng cây con (rooted subtree).
Định nghĩa bài toán con.
Bài toán ở dạng này với đầu vào là một cây có gốc r Khi đó mỗi bài toán con tương ứng là một cây con có gốc u nào đó.
Hình 8: Mô hình dạng cây.
Cấu trúc con tối ưu: Cấu trúc con tối ưu của mỗi bài toán con phụ thuộc vào số
bài toán con tương ứng là số node con của cây con đó
Bài toán 7: Tam giác số.
Cho một tam giác số như hình sau:
7