Tiểu luận quy hoạch động Tiểu luận quy hoạch động Tiểu luận quy hoạch động Tiểu luận quy hoạch động Tiểu luận quy hoạch động Tiểu luận quy hoạch động Tiểu luận quy hoạch động Tiểu luận quy hoạch động Tiểu luận quy hoạch động Tiểu luận quy hoạch động Tiểu luận quy hoạch động
Trang 1TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI
TIỂU LUẬN
ĐỀ TÀI:
QUY HOẠCH ĐỘNG
Họ và tên: Bùi Đứ c Hoàng
Mã sinh viên: 20206142
Mã l ớp: 129846
Mã h c ph ọ ần: MI3010
Trang 2Mục l c ụ
A Tổng quan v quy hoề ạch động 2
1 Gi ới thiệ u chung 2
a) Khái niệm 2
b) Ưu điểm 2
c) Nhược điểm 2
2 Thuật toán chia để trị 3
3 Nguyên lý tối ưu của Bellman 4
4 Đặc điểm chung của phương pháp quy hoạch động 4
5 Các bước giải bài toán tối ưu bằng quy hoạch động 5
a) Các cách tiếp cận 5
b) Các bước giải bài toán quy hoạch động 6
B Một số bài toán liên quan đế n quy hoạch động kinh điển 6
1 Bài toán tính 𝒏! 6
2 Tri n khai nh ể ị thứ c Newton (𝒂 + 𝒃)𝒏 7
3 Bài toán x p ba lôế 9
4 Bài toán tìm đường đi nhỏ nhất 11
5 Bài toán tìm dãy con chung dài nhất 11
6 Bài toán tìm dãy con đơn điệu tăng dài nhất không liên tiếp 13
C Kết luận 15
Trang 3A Tổng quan v ề quy hoạch động
1 Giới thiệu chung
a) Khái niệm
Phương pháp quy hoạch động do nhà toán học
người Mĩ Richard Bellman (1920- 1984) phát
minh vào năm 1953 Trong ngành khoa học máy
tính, quy hoạch động ( Dynamic Programming) là
một phương pháp giảm thời gian chạy của các
thuật toán thể hi n các tính ệ chất của các bài toán
con gối nhau (overlapping subproblem) và cấu
trúc con tối ưu (optimal substructure) Đây là một
phương pháp rất hiệu quả để giải nhiều bài toán
tin học, đặc bi t là nh ng bài toán tệ ữ ối ưu Những
bài toán này thường có nhiều nghiệm chấp nhận
được và mỗi nghiệm có một giá tr l n nhất hoặc ị ớ
nhỏ nhất (tối ưu) Hiện nay các bài thi trong các cuộc thi code, cu c thi hackathon ộ
đa số đều cần đến quy hoạch động Tất nhiên vẫn có cách giải khác để giải bài toán
đó Nhưng vì các cuộc thi code có giới hạn về thời gian, cũng như bộ nhớ của chương trình, nên một thuật toán hiệu quả là cực kỳ cần thiết Và trong các trường
hợp như vậy, quy hoạch động là một trong những thuật toán ết sh ức c n thiầ ết và
quan trọng
b) Ưu điểm
Quy hoạch động là ta giải các bài toán con đơn giản nh t c a bài toán m Sau ấ ủ ẹ
đó kết hợp chúng lại để tìm lời giải cho bài toán lớn lần lượt như thế cho tới khi tìm được đáp án của bài toán yêu cầu theo phương pháp quy nạp Quy hoạch động thể hiện đượ ức mạc s nh ở chỗ ới mỗ v i bài toán con, bài toán nh ỏ đã giải đượ đềc u
sẽ được lưu trữ ại và đem ra sử l dụng khi cần Do đó giúp ta tiết kiệm thời gian giải
c) Nhược điểm
Việc kết hợp các bài toán con thành bài toán l n, hay chia bài toán l n thành ớ ớ các bài toán nhỏ là m t công viộ ệc đòi hỏ ựi s nhanh nh y và ch t ch trong l p ạ ặ ẽ ậ luận Vì thế nó là m t công viộ ệc hế ứt s c khó khăn để tìm công th c truy h i ứ ồ và đôi khi đưa ta vào bế tắc Hơn nữa, khi giải với phương pháp quy hoạch động, việc xuất hiện s ố lượng bài toán con cần lưu trữ ớn là điề l u không th tránh khể ỏ Gây i
Trang 4ra hiện tượng tràn bộ nhớ, t n r t nhi u b nh ố ấ ề ộ ớ để lưu trữ, đòi hỏi máy tính phải có khối lượng b nhộ ớ lớn
2 Thuật toán chia để trị
Hay còn gọi là các bài toán con gối nhau “ Chia để trị” là một trong những phương pháp thông dụng nhất trong tin học Trong thuật toán đệ quy, nguyên lý chia để trị (devide and conquer) thường đóng vai trò cốt lõi trong việc thiết kế thuật toán Để gi i m t bài toán l n, ta chia nh nó thành h u h n các bài toán ả ộ ớ ỏ ữ ạ “ con độc lập”, gi i quyả ết từng “ bài toán con" một cách riêng lẻ ồ ổ ợ r i t h p d n lầ ời giải, liên k t l i ế ạ chúng lại thành bài toán ban đầu
Phương pháp chia để trị thường được áp dụng đối với những bài toán lớn, có thể chia nhỏ và mang b n chả ất bài toán đệ quy Quá trình đệ quy lần lượt xếp d n ầ các bài toán con vào ngăn xếp bộ nhớ và thực hiện giải các bài toán con theo thứ
tự từ đơn giản nhất cho đến phức tạp, đến khi giải được bài toán mẹ ban đầu Quy hoạch động là một dạng đặc biệt của thuật toán chia để trị Do đó quy hoạch động có th gi i bể ả ằng đệ quy ( chia để trị) nhưng ngược lại thì chưa chắc Thuật toán chia để trị được cài đặt bằng đệ quy mà trong đó những bài toán con s ẽ được giải nhiều lần, điều này dẫn đến làm tăng thời gian thực hiện chương trình Trong khi đó quy hoạch động tối ưu hơn ở chỗ thuật toán s ghi l i k t quả các bài ẽ ạ ế toán con vào trong các biến ( thường là biến mảng) và sử dụng chúng khi cần thiết
mà không ph i giả ải l i bài toán conạ Khi đó việc th c thi sự ẽ ố t n ít thời gian hơn, tăng tốc đ thực hiện chương trình, tuy nhiên việc sử d ng b nh có thộ ụ ộ ớ ể sẽ t n tài ố nguyên hơn
Một số thu t toán: ậ
Ví dụ 1: Tính s h ng th ố ạ ứN của dãy Fibonacci Công thúc đệ quy của dãy Fibonacci: F(1)=1, F(2)=1, F(N)=F(N-1) + F(N-2) v i N > 2 ớ
Lời giải( mã giả) :
Int Fibonacci (int N )
{
If (N=1) or (N=2) then F:=1
Else F:=F(N-1)+F(N-2)
}
Ví dụ 2 Tìm s Catalan th N bi t Catalan là dãy s : ố ứ ế ố thoả mãn biểu thức:
Trang 5𝐶𝑛 = { 0 𝑛ế𝑢 𝑛 = 0∑𝑛−1𝑖=0 𝐶𝑖𝐶𝑛−𝑖−1 𝑛ế𝑢 𝑛 > 0
Mã giả:
A[0]=1, A[1]=1;
For i:=1 to N+1 do{
For j:=0 to i do
A[i]+= A[j]*A[i-j-1];
}
Return A[N];
3 Nguyên lý tối ưu của Bellman
Nguyên lý tối ưu của Bellman là một nguyên lý thừa nhận mà không ch ng ứ minh
Ta biết rằng phương pháp quy hoạch động thường xuyên được dùng cho việc giải các bài toán tối ưu, bài toán yêu cầu tìm phương pháp tốt nhất trong các giải pháp có thể tìm được Và nguyên lý tối ưu của Bellman chính là cơ sở ố c t lõi cho bài toán quy hoạch động
Nguyên lý tối ưu Bellman được phát biểu như sau: “Dãy tối ưu các quyết định trong một quá trình quyết định nhiều giai đoạn có thu c tính là dù tr ng thái và ộ ạ
các quyết định ban đầu bất kể như thế nào, nh ng quyữ ết định còn l i phạ ải tạ o thành m ột cách gi i quyả ế ối ưu không phụ thuộc vào tr t t ạng thái được sinh ra t ừ
những quyết định ban đầu”
Do đó khi ta muốn giải một bài toán bằng phương pháp quy hoạch động Trong một vài bài toán đơn giản quy hoạch động có th di n ra trong mể ễ ột bước, nhưng nếu bài toán gồm nhiều bước thì hãy chắc rằng bài toán lớn phải được xây dựng t nh ng bài toán con mừ ữ “ ” ột cách tối ưu, hay được xây d ng t nghiự ừ ệm tối
ưu của những “bài toán con” ở các bước trước, khi đó bài toán lớn mới được giải một cách tối ưu
4 Đặc điể m chung của phương pháp quy hoạch động
Với phương pháp quy hoạch động, chúng ta bắt đ u từ việc giải hữu h n ầ ạ
những bài toán con nh nhỏ ất ( bài toán cơ sở), từ đó từng bước ổng hợp, quy n p t ạ
lại đ gi i 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)
Trang 6Khi giải m t bài ộ toán theo phương pháp chia để trị, ta phải chia bài toán lớn thành hữu h n các bài toán con cùng ki u nhạ ể ỏ hơn và giải quy t lế ần lượt chúng bằng gi i thuả ật đệ quy Khi đó, trên thực tế nhi u bài toán con có k t qu ề ế ả trung gian gi ng nhau phố ải nhưng vẫn ph i tính l i nhi u l n, d n t i vi c lãng phí tài ả ạ ề ầ ẫ ớ ệ nguyên b nh và làm chộ ớ ậm tốc độ chạy
Đối với phương pháp quy hoạch động, để ối ưu bài toán và tránh việ t c phải tính toán l i m t sạ ộ ố k t qu ế ảtrùng lặp g p l i nhi u l n, hoặ ạ ề ầ ặc các kết qu ảtrung gian giống nhau Ta thường xây dựng 1 bảng phương án dùng cho việc lưu trữ các kết quả đã tìm được Mảng này thường là một mảng N chiều và được tính toán theo công thức quy hoạch ta đã tìm được
Việc áp dụng bảng phương án đã khiến quy hoạch động tối ưu hơn rất nhi u, ề giảm thiếu các quá trình tính toán, và th hi n sể ệ ức mạnh c a thu t toán quy ho ch ủ ậ ạ
động so v i các thuật toán khác Làm n i bật lên nguyên lí chia để tr ớ ổ ị
Thường thì không có bài toán hay dấu hiệu nhận biết nào cho ta biết khi nào phải dùng phương pháp quy hoạch động nhưng nếu bài toán đó thể hiện tính chất của các bài toán con gối nhau hay có cấu trúc tối ưu thì đó là lúc chúng ta nên dùng tới phương pháp quy hoạch động
5 Các bước ải bài toán t gi ối ưu bằng quy ho ạch động
a) Các cách tiếp cận
Bài toán quy ho ch ạ động thường được dùng một trong hai cách tiếp c n sau: ậ
• Top – down ( Từ trên xuống): Trong cách ti p c n này ta s chia bài ế ậ ẽ toán lớn thành các bài toán con, và gi i quy t chúng lả ế ần lượt B t cấ ứ
• Bottom-up ( Từ dưới lên): Trong cách ti p c n này, ta s gi i quy t v n ế ậ ẽ ả ế ấ
được giải trước, sau đó sẽ được dùng để xây dựng lời giải cho các bài
Trang 7tất cả các bài toán con cần thi t cho viế ệc giải quyết bài toán cho trước không được trực giác lắm
Dựa vào nguyên lý tối ưu, ta chia bài toán thành từng giai đoạn,
kích thước nhỏ hơn
tính toán lặp lại
Dựa vào bảng phương án đã có sau khi giải, ta tìm kết quả tối ưu của bài toán
ra hiệu su t tấ ốt nhất, giảm thiểu quy trình, ti t kiế ệm thời gian và b ộ nhớ, ta tìm cách phát tri n thuể ật bằng cách thu g n h ọ ệ thức truy h i ồ
B Một số bài toán liên quan đến quy ho ạch động kinh điể n
1 Bài toán tính 𝒏!
Bài toán: Hãy tính giá tr cị ủa 𝑛! khi bi t giá tr cế ị ủa n
Input: Số nguyên dương n
Output: Giá trị của 𝑛!
Phân tích bài toán:
Trang 8Ta có định nghĩa như sau 𝑛! = { 1 , 𝑛 = 0 𝑛 ∗(𝑛 − 1)! , 𝑛 > 0
Như vậy để tính được 𝑛! ta tính (𝑛 − 1)! Sau đó ghi nhớ và áp dụng cho các vòng l p sau ặ đến giá tr 0 ị
Thuật toán:
Gọi GT[n] là giá trị của 𝑛!
Ta có công thức quy hoạch động như sau: GT[n] := n*GT[n-1];
Như vậy việc tính s𝑛! ẽ được thực hiện vòng lặp:
GT[0]:=1;
For i:=1 to n do
GT[i]:= i*GT[i-1];
Kết quả: Giá tr cị ủa 𝑛! là giá tr n m trong ph n t ị ằ ầ ử GT[n]
2 Tri ển khai nhị thức Newton (𝒂 + 𝒃)𝒏
Bài toán: Hãy triển khai nhị thức Newton (𝑎 + 𝑏)𝑛 khi biết giá trị ủa n. c (Tìm các hệ s trong khai tri n) ố ể
Input: số nguyên dương n
Output: nh ịthức (𝑎 + 𝑏)𝑛 đã được triển khai
Ví dụ: v i n=ớ 2;
(𝑎 + 𝑏)2 = 𝑎2+ 2𝑎𝑏 + 𝑏2
Phân tích bài toán:
Nhị thức Newton được triển khai theo công thức như sau:
(𝑎 + 𝑏)𝑛= ∑ 𝑛 𝐶𝑛 𝑎𝑘𝑏𝑛−𝑘
𝑘=0
Với 𝐶𝑛= 𝑛( 𝑛−1 𝑛−2 … 𝑛−𝑘+1 )( ) ( )
𝑘! = 𝑘! 𝑛−𝑘 !(𝑛! ) Như vậy muốn triển khai được nhị thức Newton ta phải tính được 𝐶𝑛 v i 0ớ ≤
𝑘 ≤ 𝑛
Ta có công thức tính tổ h p ch p k cợ ậ ủa n:
Trang 9𝐶𝑛𝑘= { 1 𝑘 = 0;𝑘 = 𝑛 𝐶𝑛−1𝑘−1 + 𝐶𝑛−1𝑘 1 ≤ 𝑘 ≤ 𝑛 − 1
• Ta xây dựng một bảng C g m n+1 dòng và n+1 cồ ột biểu di n ph n t t ễ ầ ử ừ
0 đến n
• C[i, j] lưu trữ gí tr c a Newị ủ ton(i, j) theo quy tắc sau ( quy tắc tam giác Pascal):
o C[0,0]=1;
o C[i, 0]=1;
o C[i, i] =1 với 0< i≤ 𝑛
o C[i, j] = C[i-1, j-1] + C[i-1, j] v i 0<j<i n ớ ≤
•C(n, k) lưu trữ Newton(n,k)
Thuật toán:
Từ việc phân tích bài toán trên, ta sử ụng phương pháp quy hoạch động để d giải bài toán như sau:
Int Newton(int n, int k){
Int C[n+1,n+1], i, j;
C[0,0]=1;
For i:=1 to n do{
C[i,0]=1;
C[i,i]=1;
For j:=1 to j do{
C[i,j]=C[i-1, j-1] + C[i-1, j];
}
}
Return C[n,k];
}
j
i
Trang 10
3 Bài toán xếp ba lô
Bài toán: Có một ba lô có thể chứa tối đa trọng lượng W và có n đồ ật, m i v ỗ
đồ vật có trọng lượng 𝑤𝑖 và giá tr ị tương ứng 𝑏𝑖 ( 1≤ 𝑖 ≤ 𝑛) W, wi i, b là các số
nguyên Hãy ch n và s p x p ọ ắ ế
Input: W, n ,wi, bi là các giá trị nguyên
Output: Cách s p xắ ếp đồ ật v vào trong túi sao cho ta thu được chiếc túi mang được giá tr l n nhất ị ớ
Ví dụ: Cho một cái túi đựng được tối đa 7kg, có 4 đồ ậ v t có trọng lượng và giá trị tương ứng:
• Giá trị tương ứng: 1 4 5 7
Trang 11Yêu cầu: Tìm giá tr l n nhị ớ ất mà túi có th lể ấy được Biết m i vỗ ật có th ể được lấy ho c không l y ặ ấ
Phân tích bài toán:
• Sử d ng mụ ảng K[0…n,0…W] để lưu trữ giải phải của bài toán con
• Ban đầu K[0,j]=K[i,0] với mọi i,j
• Sau đó K[i,j] sẽ được tính theo K[i-1,j] hoặc K[i-1,j-𝑤𝑖]
Giá trị Trọng
lượng
Thuật toán:
Int Caitui( int giatri[], int trongluong[], int n, int W){
Int K[n+1][W+1];
For i:=0 to n{
For w to W{
then w]=0;
If ( i==0 or w==0) K[i][
-1][w];
Else if ( w < trongluong[i]) then K[i][w] = K[i
-1][w], giatri[i] + K[i-1][w - trongluong[i]); Else K[i][w] = max( K[i
}
}
Return K[n][W];
}
Trang 124 Bài toán tìm đường đi nhỏ nhất
Bài toán: Cho bảng A[] có kích thước N x M ( N hàng, M cột) ạn được B phép đi sang trái, đi sang phải và đi xuống ô chéo dướ Khi đi qua ô (i, j)i điểm bạn nhận được là A[i][j]
Hãy tìm đường đi từ ô (1, 1) tới ô (M, N) sao cho tổng điểm là nhỏ nhất
1
3 3
1 2 3
4 8 2
1 5 3
8
Giải thích test : Đường đi (1,1) → (1,2)→ (2,3)→ (3,3)
Thuật toán:
Int a[n+5][m+5];
Int F[n+5][m+5];
For i:=1 to n do{
For j:=1 to m do{
If( i=1 and j =1) F[i][j]=a[i][j];
Else if ( i=1) F[i][j] = a[i][j] + F[i][j-1];
Else if ( j=1) F[i][j] = a[i][j] + F[i-1][j];
Else F[i][j] = a[i][j] + min(F[i-1][j-1], F[i-1][j], F[i][j-1]);
}
}
Return F[n][m];
5 Bài toán tìm dãy con chung dài nh ất
Trang 13Bài toán: Cho 2 chuỗi X và Y, tương ứng có độ dài lần lượt là m và n Tìm dãy con chung dài nhất c a X và Y (các ph n t không nh t thiủ ầ ử ấ ết phải liên ti p ế nhau)
Ví dụ: X=<B, U, N, H> và Y=<B, U, I, H, O, A, N, G >
Kết qu : ả Độ dài c a dãy con chung dài nh t là 3 là chu i <B, U, H> hoủ ấ ỗ ặc
<B, U, N>
Phân tích bài toán:
• Ta ký hi u: ệ
o 𝑋𝑖= 𝑥1𝑥2 𝑥𝑛 là thứ tự các phầ ử ủa X.n t c
o 𝑌𝑗= 𝑦1𝑦2 𝑦𝑛là thứ ự các phầ t n t cử ủa Y
• Ta dùng mảng C[0…n,0…m] để lưu giá trị độ dài c a các dãy con ủ chung dài nhất của các cặp ti n t ề ố
• Gọi C[i, j] là độ dài dãy con chung dài nhất của 𝑋𝑖 𝑣à 𝑌𝑗
• Khi đó độ dài dãy con chung dài nhất của X và Y là C[n,m]
• Ta có: C[i, j] = { 𝐶[𝑖 − 1, 𝑗 − 1] + 1 𝑖, 𝑗 > 0 , 𝑥0 𝑖 = 0 ℎ𝑜ặ𝑐 𝑗 = 0𝑖= 𝑦𝑖
𝑚𝑎𝑥(𝐶[𝑖 − 1, 𝑗], 𝐶[𝑖, 𝑗 − 1] 𝑖, 𝑗 > 0, 𝑥 ≠ 𝑦𝑖 𝑖
i
j
Trang 148 G 0 1 2 3 3
Kết luận: Vậy dãy con chung dài nhấ ủa BUIHOANG và BUNH là 3 là dãy t c BUH hoặc BUN
Thuật toán:
Int C[m,n];
For i:=0 to m
For j:=0 to n
i=0 or j=0) then C[i, j]=0;
If(
Else
) then C[i,j] = C[i-1,j-1] + 1;
If (Xi = Yj
C[i,j]= max(C[i,j-1], C[i-1,j]);
Else
6 Bài toán tìm dãy con đơn điệu tăng dài nhất không liên tiếp
Bài toán: Cho một dãy s nguyên g m n ph n tố ồ ầ ử 𝑎1, 𝑎2, , 𝑎𝑛 Hãy tìm một dãy con của dãy đã cho sao cho các phầ ử là đơn điệu tăng.n t
Input: Dòng đầu s ố nguyên n là độ dài c a dãy ủ
Dòng sau gồm n ph n tầ ử 𝑎1,𝑎 , , 𝑎2 𝑛 cách nhau một dấu cách
Output: Độ dài của dãy con tăng dài nhất
Danh sách các phần tử trong dãy con đó
Ví dụ:
10
3 4 5 7 8 2 1 2 9 3
6
3 4 5 7 8 9
Phân tích bài toán:
• Trước tiên ta sẽ l p mậ ột mảng A[0…n] để lưu các giá trị ủ c a
𝑎1, 𝑎2, , 𝑎𝑛 và một mảng con L
• Với i chạy t 0 t i n ta s dùng mừ ớ ẽ ảng L để lưu lại giá trị theo công thức truy hồi
Trang 15Ví dụ với A[2]=5 ta xét i ch y t ạ ừ 0 đến 2, nếu như không có giá trị A[i] nào lớn hơn A[2] thì L[2] = L[1]+1 Còn nếu như tồ ạn t i giá tr i ị thuộc (0,2) sao cho A[i] > A[2] thì ta sẽ tính lại L[i]=1 tạ ị trí lớn hơn đó i v Lặp l i cho t i khi ch y hạ ớ ạ ết các giá trị
• Ta tìm được công thức truy hồi:
{𝑳[𝒊] = 𝟏 𝒏ế𝒖 ∃𝒋 = (𝟎, 𝒊) 𝒔𝒂𝒐 𝒄𝒉𝒐 𝒂𝒊< 𝒂𝒋
𝑳 𝒊 = 𝑴𝒂𝒙𝑳 𝒋[ ] [ ]𝟎≤𝒋<𝒊+ 𝟏 𝒏ế𝒖 𝒂𝒊> 𝒂 ∀𝒋 = 𝟎, 𝒊𝒋 ( )
Mảng
A
Mảng
L
Kết luận: Vậy độ dài chuỗi con dài nhất là 6: <3, 4, 5, 7, 8, 9>
Thuật toán:
Int A[100],Int L[100];
Int Lmax //lưu giá trị max từ u tđầ ới phần t i ử L[0]=1;
For i:= 1 to n do{
Lmax=0;
For j:=0 to i
{
If ( A[i] > A[j] )
If (L[j]>Lmax) then Lmax=L[j];
}
L[i]=Lmax +1;
}