Professional Documents
Culture Documents
Kĩ thuật lập trình - Chương 7 - Quy hoạch động
Kĩ thuật lập trình - Chương 7 - Quy hoạch động
Programming Techniques
Ts. Nguyễn Đức Thuần
BM Hệ thống Thông Tin
Giới thiệu môn học
Page 2
QUI HOẠCH ĐỘNG
(Dynamic Programming)
Page 3
Chương 7: QUI HOẠCH ĐỘNG
I. NỘI DUNG
Giới thiệu
Phương pháp
Các ví dụ
Ưu điểm và khuyết điểm
Page 4
Chương 7: QUI HOẠCH ĐỘNG
I. GIỚI THIỆU
Page 5
Chương 7: QUI HOẠCH ĐỘNG
• Quy hoạch động là một phương pháp giảm thời gian chạy của các thuật
toán có các bài toán con trùng lắp (overlapping subproblem) và cấu trúc
con tối ưu (optimal substructure).
• Quy hoạch động sẽ giải một bài toán con một lần và lời giải của các bài
toán con sẽ được lưu giữ lại nhằm khỏi
giải lại các bài toán con.
• Quy hoạch động là quá trình tiếp cận thuật toán theo quá trình từ dưới
lên (bottom-up).
Chú ý:
Kỹ thuật Chia để trị, thường phân bài toán đã cho thành các bài
toán độc lập.
Page 6
Chương 7: QUI HOẠCH ĐỘNG
Có hai tính chất quan trọng mà một bài toán tối ưu cần phải thoả mãn để có
thể áp dụng quy hoạch động để giải nó là:
1. Cấu trúc con tối ưu: Để giải được bài toán đặt ra một cách tối ưu,
mỗi bài toán con cũng phải được giải một cách tối ưu.
2. Số lượng các bài toán con phải không quá lớn: Rất nhiều các
bài toán có thể giải được nhờ quy hoạch động, nhưng việc làm này
là không hiệu quả do số lượng các bài toán con tăng theo hàm mũ.
Một đòi hỏi quan trọng đối với quy hoạch động là tổng số các bài
toán con cần giải là không quá lớn, cùng lắm phải bị chặn bởi một
đa thức của kích thước dữ liệu vào.
Lập bảng
+ cài đặt
Page 8
Chương 7: QUI HOẠCH ĐỘNG
Page 10
Chương 7: QUI HOẠCH ĐỘNG
Chú ý: Đây là phương pháp lập trình qui hoạch động dùng bộ nhớ để lưu
kết quả trung gian (Memoization)
Page 11
Chương 7: QUI HOẠCH ĐỘNG
Cách 3: Lập trình qui hoạch động, dùng Table để lưu trữ
B1: Dùng 1 mảng lưu trữ F[i], i=1,n
B2: Cơ sở: F[1]=1; F[2]=1;
B3: Truy hồi F[i]=F[i-1]+F[i-2];
B4: F[n] kết quả.
Page 12
Chương 7: QUI HOẠCH ĐỘNG
Page 13
Chương 7: QUI HOẠCH ĐỘNG
Page 14
Chương 7: QUI HOẠCH ĐỘNG
Page 15
Chương 7: QUI HOẠCH ĐỘNG
Làm sao có công thức
Truy hồi đó hè?
Định nghĩa các bài toán con:
Dn là số cách viết n thành tổng các số 1, 3, 4
• Tìm thấy công thức truy hồi
Dn=Dn-1+Dn-3+Dn-4 với n>4
B1: Dùng mảng 1 chiều để lưu trữ
Biểu diễn:
B2: Cơ sở: (Giá trị ban đầu:) D1=1; D2=1; D3=2; D4=4
N=x1+x2+..+xn
B3: Truy hồi: Nếu buộc số hạng cuối là 1,
Thì có Dn-1 cách khác nhau.
Page 17
Chương 7: QUI HOẠCH ĐỘNG
• Lần 1: 0 1 2 3 .. .. .. k
1 1 0 0 0
• Lần 2: 0 1 2 3 .. .. .. k
1 2 1 0 0
• ….
Page 18
Chương 7: QUI HOẠCH ĐỘNG
4. Dãy con có tổng bằng P: Cho một dãy k các số nguyên, và một số S.
Hỏi tồn tại một dãy con của dãy đã cho có tổng bằng S? Nếu có liệt kê?
Thử làm bài đổi tiền xem
- Input: {0,10,8,7,6,6,6,6}; S=25;
- Output: Có dãy con 7 8 10
B1: Dùng mảng 2 chiều P[n][n] để lưu giữ trạng thái (n=max(k,S)) với
P[i][j] = 1 nếu có một dãy con từ a[1] đến a[i] có tổng bằng j, (ngược lại =
0)
Nhận xét: P[i][0]=1; P[0][i]=0;
P[i-1][j] = 1 P[i][j] =1
P[i-1][j-a[i]]=1 P[i][j] =1
B2: Cơ sở: P[i][0]=1; P[0][i]=0;
B3: Truy hồi: for(i=1;i<=n;i++) for(j=1;j<=S;j++)
if ((P[i-1][j]==1)||(P[i-1][j-a[i]]==1)) P[i][j]=1;
Page 19
Chương 7: QUI HOẠCH ĐỘNG
Page 20
Chương 7: QUI HOẠCH ĐỘNG
Luyện tập: Thử nêu cách giải bài toán chia kẹo:
Có N gói kẹo, gói thứ i có A[i] cái kẹo. Yêu cầu: Hãy tìm cách chia các gói
kẹo này thành 2 phần sao cho độ chênh lệch giữa tổng số kẹo ở hai phần
là ít nhất có thể được 0 <1000, 2<=N<=10000
Page 22
Chương 7: QUI HOẠCH ĐỘNG
// Hàm đệ qui
Page 24
Chương 7: QUI HOẠCH ĐỘNG
Chú ý: Bài tập còn có thể phát biểu: Hãy tính số cách biểu diễn số
tự nhiên n thành tổng của m số tự nhiên sắp theo trật tự không tăng.
Thí dụ, với n = 7, m = 4 ta có:
7 = 7 + 0 + 0 + 0 = 6 + 1 + 0 + 0 ….
Page 27
Chương 7: QUI HOẠCH ĐỘNG
6. Tìm dãy con đơn điệu dài nhất Cho a là một dãy có n phần tử
a1,a2,..,an. Một dãy con của a là dãy ai1,ai2,..aik với i1<i2<..<ik
Tìm dãy con của a, đơn điệu tăng dài nhất.
Ví dụ:
1 2 3 4 5 6 7 8 9 10
5 2 3 4 9 10 5 6 7 8
B1: Khai báo mảng: a [0..n+1] lưu trữ các phần tử đã cho
L[0..n+1] lưu trữ độ dài các dãy con tăng dần
cụ thể L[i] là độ dài dãy con đơn điệu tăng dần kể từ a[i]
Gán a[0]=-; a[n+1]=+
B2: Cơ sở: L[n+1] =1
Page 28
Chương 7: QUI HOẠCH ĐỘNG
i 0 1 2 3 4 5 6 7 8 9 10 11
a - 5 2 3 4 9 10 5 6 7 8 +
L 9 5 8 7 6 3 2 5 4 3 2 1
Page 29
Chương 7: QUI HOẠCH ĐỘNG
i 0 1 2 3 4 5 6 7 8 9 10 11
a - 5 2 3 4 9 10 5 6 7 8 +
L 9 5 8 7 6 3 2 5 4 3 2 1
T 2 8 3 4 7 6 11 8 9 10 11
Page 30
Chương 7: QUI HOẠCH ĐỘNG
Page 31
Chương 7: QUI HOẠCH ĐỘNG
k = L[n][m];
i=n; j=m;
while (i>0)
{ if (a[i]==b[j]) {printf (“%3d”, a[i]); i=i-1;j=j-1;} else
if (L[i-1][j] > L[i][j-1]) i=i-1; else j=j-1;
}
Page 32
Chương 7: QUI HOẠCH ĐỘNG
Page 34
Chương 7: QUI HOẠCH ĐỘNG
Cài đặt:
// Co so
L[0]=0;
for(i=1;i<=n;i++)
L[i]=v[i];
// Truy hoi
for(i=1;i<=n;i++)
for(j=i-1;j>0;j--)
if ((b[j]<=a[i])&&(L[j]+v[i]>L[i])) L[i]=L[j]+v[i];
Truy vết:
// So tien thu duoc cao nhat
int max=L[1];
int k;// Cong viec cuoi cung trong day cac cong viec cho thue
for(i=1;i<=n;i++)
if (L[i]>max) {max=L[i];k=i;}
printf("\n So tien cho thue duoc lon nhat: %d",max);
Page 35
Chương 7: QUI HOẠCH ĐỘNG
Truy vết:
while (k>0)
{ printf("\n cong viec thu %3d, bat dau: %3d, ket thuc: %3d",k,a[k],b[k]);
j=k-1;
while ((L[j]+v[k]!=L[k])||(b[j]!=a[k])) j=j-1;
k=j;
}
Page 36
Chương 7: QUI HOẠCH ĐỘNG
Lời giải gợi ý: sắp xếp các đơn đặt hàng theo thời điểm kết thúc
Bài toán liên quan với 1 tham số: Số cuộc họp nhiều nhất nhất khi xét đến
công việc thứ i.
Cơ sở: L[i] = 1, i=1,n
Truy hồi: L[i] = max(L[j] + 1), nếu (b[j] <=a[i]) && (j<i)
Page 37
Chương 7: QUI HOẠCH ĐỘNG
8. Bài toán xếp Balo: Một chiếc Balo có thể tích là Pmax.
Có n vật, vật thứ i có thể tích là: P[i] và giá trị w[i].
Hãy tìm cách xếp các vật vào Balo sao cho tổng giá trị là lớn nhất.
B1: Dùng mảng 2 chiều để lưu trữ phương án lấy vật L[0..n][0..Pmax]
L[i][j] : tổng giá trị lớn nhất của vali khi xét từ vật 1 vật i và thể tích
chưa vượt quá j.
Page 38
Chương 7: QUI HOẠCH ĐỘNG
Page 39
Chương 7: QUI HOẠCH ĐỘNG
// Truy hồi
for (i=1; i<=n; i ++)
for (j=1;j<=Pmax; j++)
{L[i][j] = L[i-1][j];
if ((j>=w[i]) && (L[i][j] < P[i]+ L[i-1][j-w[i]])
L[i][j]= P[i]+ L[i-1][j-w[i]];
}
Page 40
Chương 7: QUI HOẠCH ĐỘNG
j= Pmax;
for (k=n; k>=0; k - -)
if (L[k][j] != L[k-1][j])
{ printf(“\n Vat thu: %3d, gia tri: %3d, the tich: %3d”,k,P[k],w[k]);
j=j-w[k];}
Page 41
Chương 7: QUI HOẠCH ĐỘNG
Page 42
Chương 7: QUI HOẠCH ĐỘNG
9. Tích n ma trận
Nhận xét: Số lượng phép toán nhân thực hiện phụ thuộc vào 2 tham số: số
hàng & số cột. Bảng phương án: 2 chiều.
Tổ chức dữ liệu:
Kích thước của n ma trận được lưu thành 1 mảng n+1 phần tử.
Kích thước ma trận thứ i là: a[i]xa[i+1]
Gọi F[i][j] là số phép nhân cần thực hiện để nhân đoạn ma trận liên tiếp:
MiMi+1.….Mj (1 i j n).
Khi đó F[i][i] = 0 với mọi i.
Để tính Mi.Mi+1.….Mj ta có thể có nhiều cách kết hợp: Mi.Mi+1.….Mj =
(Mi.Mi+1.….Mk).(Mk+1.….Mj-1.Mj) với i k <j. Với mỗi cách kết hợp (phụ
thuộc vào cách chọn vị trí k).
Page 43
Chương 7: QUI HOẠCH ĐỘNG
Page 44
Chương 7: QUI HOẠCH ĐỘNG
Page 45
Chương 7: QUI HOẠCH ĐỘNG
9. Tích n ma trận
A × B × C × D
[20×2] [2×30] [30×12] [12×8]
Điền bảng phương án:
F[i][i+1] = aixai+1xai+2 j=1 2 3 4
Điền F[i][j]: Ví dụ i=1 0 1200 1200
F[1][3] = min { 2 0 720
Page 47
Chương 7: QUI HOẠCH ĐỘNG
Page 48
Chương 7: QUI HOẠCH ĐỘNG
Page 49
Cám ơn đã theo dõi
Page 50