Tải bản đầy đủ (.pdf) (7 trang)

Quy Hoạch Động trạng thái

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (73.81 KB, 7 trang )

PHƯƠNG PHÁP QUY HOẠCH ĐỘNG TRẠNG THÁI
Nguyễn Duy Dũng
Trường THPT Chuyên Hà Tĩnh
I. ĐẶT VẤN ĐỀ
Quy hoạch động là một phương pháp thường được sử dụng để giải các bài toán
trong tin học. Trong một số bài toán giải bằng phương pháp này khi xét tại mỗi
bước thường có nhiều khả năng lựa chọn ta gọi là các trạng thái. Chẳng hạn để
tìm lời giải cho bài toán ta đi lần lượt từ bước 1 đến bước thứ K, tại bước thứ i
có nhiều lựa chọn (trạng thái) khác nhau, để tìm hướng đi đúng cho bước thứ i
lại dựa vào các trạng thái của bước thứ i-1 và có thể xác định bằng một công
thức cụ thể nếu tập các trạng thái là hữu hạn. Khi gặp các bài toán loại này ta
thường giải bằng phương pháp quy hoạch động trạng thái.
Trong quá trình giảng dạy các lớp chuyên tin học và ôn luyện học sinh giỏi
quốc gia, tôi nhận thấy tài liệu viết về vấn đề này rất hạn chế. Để hiểu hơn về
phương pháp này chúng ta cùng tìm hiểu một bài toán cụ thể.
II. BÀI TOÁN
Chọn ô - HSG QG 2006 (SELECT)
Cho một bảng hình chữ nhật kích thước 4×n ô vuông. Các dòng được đánh số
từ 1 đến 4, từ trên xuống dưới, các cột được đánh số từ 1 đến n từ trái qua phải.
Ô nằm trên giao của dòng i và cột j được gọi là ô (i,j). Trên mỗi ô (i,j) có ghi
một số nguyên aij , i =1, 2, 3, 4; j =1, 2, , n. Một cách chọn ô là việc xác định
một tập con khác rỗng S của tập tất cả các ô của bảng sao cho không có hai ô
nào trong S có chung cạnh. Các ô trong tập S được gọi là ô được chọn, tổng các
số trong các ô được chọn được gọi là trọng lượng của cách chọn.
Tìm cách chọn sao cho trọng lượng là lớn nhất.
Ví dụ: Xét bảng với n=3 trong hình vẽ dưới đây:
Cách chọn cần tìm là tập các ô S = {(3,1), (1,2), (4,2), (3,3)} với trọng lượng
32.
Input
Dòng đầu tiên chứa số nguyên dương n là số cột của bảng.
Cột thứ j trong số n cột tiếp theo chứa 4 số nguyên a


1j
, a
2j
, a
3j
, a
4j
, hai số liên
tiếp cách nhau ít nhất một dấu cách, là 4 số trên cột j của bảng.
Output
Gồm 1 dòng duy nhất là trọng lượng của cách chọn tìm được.
Example
Input
Output
3
-1 9 3
-4 5 -6
7 8 9
9 7 2
32
Hạn chế
Trong tất cả các test: n ≤ 10000, |a
ij
| ≤ 30000. Có 50% số lượng test với n ≤
1000.
III. GIẢI THUẬT VÀ CÀI ĐẶT
Tư tưởng chính:
- Mỗi cột có 4 dòng nên ta có thể dùng dãy nhị phân gồm 4 bít để biểu diễn.
Tùy vào giá trị của bít thứ k của cột thứ i bằng 0 hoặc1 cho biết dòng thứ k
của cột thứ i có được chọn hay không. (0 ≤ k ≤ 3)

- Dãy nhị phân có 4 bít ứng với 2
4
trạng thái, biểu diễn từ 0 tới 2
4
-1.
- Gọi F[i,x] là tổng trọng lượng lớn nhất xét từ cột thứ 1 tới cột thứ i và trạng
thái chọn của cột thứ i được biểu diễn bằng biến x.
- Ta có công thức quy hoạch động như sau:
F[i,x]=max(F[i-1,y])+sum(i,x)
Trong đó:
- Biến x và y là hai trạng thái tương ứng của cột thứ i và i-1. Theo yêu cầu
của bài toán thì trạng thái x và y phải thỏa mãn bít thứ k của biến x phải khác
bít thứ k của biến y vì việc chọn ô phải thỏa mãn không có hai ô nào có
chung cạnh.(Getbit(k,x)<>Getbit(k,y))
- Hàm Sum(i,x) là trọng số của cột thứ i tương ứng với trạng thái x.
Cài đặt:
Biến A chứa giá trị của bảng, biến m =2
4
-1 với m+1 là số trạng thái
Trong chương trình sử dụng một số hàm như sau:
+) Lấy giá trị bít thứ k của trạng thái x: Getbit(k,x)
Function Getbit(k,x:word):byte;
Begin
Getbit:=(x shr k)and 1;
End;
+) Hàm kiểm tra trạng thái x có thỏa mãn yêu cầu bài toán không (không có
hai ô nào có chung cạnh), nghĩa là bít thứ k và bít thứ k-1 của trạng thái x phải
khác nhau:
Function Ok(x:word):boolean;
Begin

Ok:=false;
For k:=1 to 3 do
If (getbit(k-1,x)=1)and(getbit(k,x)=1) then
Exit;
Ok:=true;
End;
+) Hàm kiểm tra trạng thái x và trạng thái y có thỏa mãn yêu cầu bài toán
không (không có hai ô nào có chung cạnh), nghĩa là bít thứ k của trạng thái x
và bít thứ k-1 của trạng thái y phải khác nhau:
Function Check(x,y:word):boolean;
Begin
Check:=false;
For k:=0 to 3 do
If (getbit(k,x)=1)and(getbit(k,y)=1) then
Exit;
Check:=true;
End;
+) Tính trọng lượng của cột thứ i ứng với trạng thái x:
Function sum(i,x:word):longint;
Var T:longint;
Begin
T:=0;
For k:=0 to 3 do
If (getbit(k,x)=1) then
T:= T+A[k+1,i];
Sum:=T;
End;
+) Thủ tục chính:
Procedure process;
Var max:longint;

y,i:word;
Begin
For i:=1 to n do {Xét lần lượt n cột}
For x:=0 to m do {Với mỗi cột i xét 2
4
trạng thái}
If Ok(x) then {Nếu trạng thái x thỏa mãn bài toán}
Begin
max:=-vc;
{Tìm trạng thái y của cột thứ i-1 có tổng trọng lượng lớn nhất}
For y:=1 to m do
If check(x,y)and(ok(y))then
If max<F[i-1,y] then
max:=F[i-1,y];
F[i,x]:=max+sum(i,x)
End;
End;
+) Thủ tục in kết quả:
Procedure printresult;
Var Max:longint;
ff:text;
Begin
{Chú ý thêm trường hợp tất cả A[i,j]<0}
{Tìm giá trị lớn nhất trong các trạng thái của cột thứ n}
Max:=-vc;
For x:=0 to m do
If ok(x)and (max<F[n,x]) then
Max:=F[n,x];
Assign(ff,fo); rewrite(ff);
Writeln(ff,max);

Close(ff);
End;
Nhận xét
- Độ phức tạp thuật toán: O(2
4*
2
4*
N) đủ để giải quyết bài toán trên.
- Để giảm độ phức tạp của thuật toán ta có thể dùng 1 mảng B lưu những trạng
thái thỏa mãn yêu cầu không có hai ô nào cùng cột có chung cạnh kết hợp
với cấu trúc dữ liệu Foward Star để ứng với mỗi trạng thái x ta có danh sách
các trạng thái y thỏa mãn.
IV. MỘT SỐ BÀI TOÁN ỨNG DỤNG
Bài 1: Chuyến du lịch (TRIP)
Trong kì nghỉ hè năm nay sherry được bố thưởng cho 1 tour du lịch quanh N
đất nước tươi đẹp với nhiều thắng cảnh nổi tiếng (vì sherry rất ngoan ). Tất
nhiên sherry sẽ đi bằng máy bay.
Giá vé máy bay từ đất nước i đến đất nước j là C
ij
(dĩ nhiên C
ij
có thể khác C
ji
).
Tuy được bố thưởng cho nhiều tiền để đi du lịch nhưng sherry cũng muốn tìm
cho mình 1 hành trình với chi phí rẻ nhất có thể để dành tiền mua quà về tặng
mọi người ( Các chuyến bay của sherry đều được đảm bảo an toàn tuyệt đối ).
Bạn hãy giúp sherry tìm 1 hành trình đi qua tất cả các nước, mỗi nước đúng 1
lần sao cho chi phí là bé nhất nhé.
Input

Dòng 1: N (5 < N < 16)
Dòng thứ i trong N dòng tiếp theo: Gồm N số nguyên, số thứ j là C
ij
(0 < C
ij
<
10001)
Output
Gồm 1 dòng duy nhất ghi chi phí bé nhất tìm được
Example
Input
Output
6
0 1 2 1 3 4
5 0 3 2 3 4
4 1 0 2 1 2
4 2 5 0 4 3
2 5 3 5 0 2
5 4 3 3 1 0
8
Hướng dẫn:
- Ta nhận thấy đây là bài toán tìm đường đi Hamilton, một bài toán khá quen
thuộc: cho N đỉnh, tìm đường đi sao cho mỗi đỉnh được thăm duy nhất một
lần, và chi phí thăm N đỉnh là thấp nhất.
- Với dạng toán này, thông thường nếu N nhỏ (≤10), ta có thể giải quyết bài
toán bằng phương pháp nhánh cận. Nhưng nếu giới hạn N tăng lên đến 20,
thì việc sử dụng phương pháp nhánh cận để giải quyết sẽ không còn khả thi
nữa. Trong trường hợp này, ta có cách tiếp cận khác để giải quyết bài toán
một cách tối ưu hơn, với độ phức tạp O(N
2

*2
N
).
- Dãy nhị phân có N bít ứng với 2
n
trạng thái, biểu diễn từ 0 tới 2
n
-1 cho biết
các đỉnh đã được thăm hay chưa.
- Gọi F[i,x] là tổng chi phí nếu sherry đang ở Đất nước i và trạng thái các
nước đã đi qua được lưu vào biến.
- Công thức Quy hoạch động:
F[i,x] = min( F[j,y] + C[j,i] )
Trong Đó
- j là đất nước đã được đánh dấu đi qua trong x.
- ylà trạng thái giống như trạng thái x nhưng đất nước i chưa được đánh dấu.
Bài 2: Cô gái chăn bò (COWGIRL)
Trên một thảo nguyên nhỏ bé có 1 gia đình gồm 3 anh em: 2 người anh trai là
Nvutri và Andorea còn người em gái là Lola. Cuộc sống gia đình khá giả
nhưng gia đình có truyền thống chăn nuôi và muốn để các con tự lập nên cha
mẹ 3 người quyết định để các con hằng ngày sẽ đi chăn 1 số bò nào đó (tùy ý 3
người con).
Thảo nguyên là 1 cánh đồng chia làm M*N ô vuông, mỗi con bò chỉ đứng
trong 1 ô và mỗi ô chỉ chứa 1 con bò.Chỉ có 1 quy tắc duy nhất là không bao
giờ được để 4 con bò tạo thành 1 hình vuông 2*2 hoặc để trống 1 khu đất 2*2.
Hai người anh mải chơi nên đã hối lộ kem để Lola chăn bò 1 mình. Lola
muốn biết tất cả có bao nhiêu cách xếp bò thỏa mãn quy tắc trên để đề phòng
mọi trường hợp. Vì con số này rất lớn nên hãy giúp Lola tính toán con số này.
Input
Dòng đầu gồm 1 số T duy nhất là số test (T ≤ 111)

T dòng tiếp theo gồm 2 số M, N cho biết kích thước của thảo nguyên (M*N ≤
30)
Output
Gồm T dòng, mỗi dòng ứng với 1 test là số cách xếp bò của test đó.
Example
Input
Output
1 1
1
2
Hướng dẫn:
- Ta thấy M*N<=30 nên tồn tại một số M hay N không lớn hơn 5. Giả sử là
M là số dòng không quá 5. Ta có thể sử dụng số có không quá 5 bit nhị phân
Để mô tả trạng thái chọn ở mỗi cột.
- Gọi F[i,x] là số cách xếp bò thỏa mãn yêu cầu bài toán xét từ cột thứ 1 tới
cột thứ i và trạng thái chọn của cột thứ i được biểu diễn bằng biến x
- Công thức Quy hoạch động:
F[i,x] = F[i,x] + F[i-1,y] )
Bài 3: Đàn bò hỗn loạn (MIXUP)
Mỗi trong N cô bò (4 <= N <= 16) của bác John có một số seri phân biệt S_i
(1 <= S_i <= 25,000). Các cô bò tự hào đến nỗi mỗi cô đều đeo một chiếc vòng
vàng có khắc số seri của mình trên cổ theo kiểu các băng đảng giang hồ.
Các cô bò giang hồ này thích nổi loạn nên đứng xếp hàng chờ vắt sữa theo
một thứ tự gọi được gọi là 'hỗn loạn'.
Một thứ tự bò là 'hỗn loạn' nếu trong dãy số seri tạo bởi hàng bò, hai số liên
tiếp khác biệt nhau nhiều hơn K (1 <= K <= 3400). Ví dụ, nếu N = 6 và K = 1
thì 1, 3, 5, 2, 6, 4 là một thứ tự 'hỗn loạn' nhưng 1, 3, 6, 5, 2, 4 thì không (vì hai
số liên tiếp 5 và 6 chỉ chênh lệch 1).
Hỏi có bao nhiêu cách khác nhau để N cô bò sắp thành thứ tự 'hỗn loạn'?
Input

* Dòng 1: Hai số N và K cách nhau bởi khoảng trắng.
* Dòng 2 N+1: Dòng i+1 chứa một số nguyên duy nhất là số seri của cô bò
thứ i: S_i
Output
* Dòng 1: Một số nguyên duy nhất là số cách để N cô bò sắp thành thứ tự
'hỗn loạn'. Kết quả đảm bảo nằm trong phạm vi kiểu số nguyên 64-bit.
Example
Input
Output
4 1
3
4
2
1
2

×