Lí do chọn đề tài Hiện nay tài liệu dạng chuyên đề nâng cao phục vụ cho việc bồi dưỡng học sinh giỏi môn Tin học là chưa thật sự đầy đủ và tổng quát, đặc biệt là những chuyên đề khá mới
Trang 1TỔ TOÁN TIN
ĐỀ TÀI:
Người thực hiện: LÊ VĂN TRƯỜNG
Giáo viên: Tin học
Trang 2PHƯƠNG PHÁP GIẢI BÀI TOÁN TIN BẰNG QUY HOẠCH ĐỘNG
A PHẦN MỞ ĐẦU
I Lí do chọn đề tài
Hiện nay tài liệu dạng chuyên đề nâng cao phục vụ cho việc bồi dưỡng học sinh giỏi môn Tin học là chưa thật sự đầy đủ và tổng quát, đặc biệt là những chuyên đề khá mới và rất khó của thế giới, giờ đã được đưa vào các đề thi học sinh giỏi Quốc gia như: Quy hoạch động, Luồng cực đại trên mạng,…
Từ thực tiễn giảng dạy tin tại trường THPT Chuyên Hùng Vương tôi thấy rằng
để đạt hiệu quả cao trong bồi dưỡng học sinh giỏi, cần có cách thiết kế bài giảng cho phù hợp với nội dung kiến thức dựa trên tài liệu chuyên đề đầy đủ rõ ràng từ lý thuyết đến bài tập và theo đúng xu thế chung của các kì thi học sinh giỏi các cấp hiện nay và trong tương lai, điều kiện tiến quyết để mang lại thành tích cao cho đội tuyển học sinh giỏi trong các kì thi
Xuất phát từ cơ sở trên, tôi đã chọn đề tài “Phương pháp giải bài toán tin bằng quy hoạch động”, sáng kiến này sẽ giúp học sinh của trường THPT Chuyên Hùng Vương vận dụng các kiến thức vào làm tốt các dạng đề thi Quốc gia có liên quan về luồng cực đại, phục vụ cho việc bồi dưỡng học sinh giỏi của trường
II Mục đích của đề tài
- Giới thiệu phương pháp giải các bài toán - tin bằng quy hoạch động (QHĐ)
- Các bước giải bài toán - tin bằng phương pháp QHĐ
- Giải một số bài toán bằng phương pháp quy hoạch động điển hình
- Một số bài tập áp dụng có hướng dẫn giải thuật cho học sinh tự làm
- Từ đó giúp học sinh của trường THPT Chuyên Hùng Vương vận dụng các kiến thức vào làm tốt các dạng đề thi Quốc gia có dạng quy hoạch động
Trang 3III Nhiệm vụ của nghiên cứu
- Giới thiệu phương pháp giải các bài toán - tin bằng quy hoạch động (QHĐ)
- Các bước giải bài toán - tin bằng phương pháp QHĐ
- Hướng dẫn giải một số bài toán bằng phương pháp quy hoạch động điển hình
- Một số bài tập áp dụng có hướng dẫn giải thuật cho học sinh tự làm
- Đưa ra một số bài tượng tự để các em học sinh giỏi vận dụng thực hành trên máy
IV Đối tượng nghiên cứu
- Học sinh giỏi tin học 11, 12 của trường THPT Chuyên Hùng Vương
V Phương pháp nghiên cứu
- Kết hợp thực tiễn giáo dục ở trường THPT Chuyên Hùng Vương và xu thế ra
đề thi học sinh giỏi Quốc gia của Bộ giáo dục và đào tạo
- Có tham khảo các tài liệu bồi dưỡng học sinh giỏi trong và ngoài nước
- Tham khảo một số dạng đề thi học sinh giỏi Quốc gia của Bộ giáo dục và đào tạo dạng quy hoạch một số năm gần đây
B NỘI DUNG
I Cơ sở lí luận
- Các cách tiếp cận về tri thức mới, hiện đại của học sinh trong trường THPT Chuyên Hùng Vương là rất khó khăn vì thiếu tài liệu chuyên sâu về bồi dưỡng học sinh giỏi tin học tiếng Việt, nếu có thì cũng chưa thật đầy đủ, tổng quát, còn tài liệu tiếng Anh thì nhiều mà khả năng đọc hiểu của các em thì chưa thật sự tốt
Trang 4- Vì vậy tôi đã tham khảo tài liệu trong và ngoài nước để viết lên sáng đề tài về phương pháp quy hoạch động từ lý thuyết đến thuật toán và có một số bài toán cho các em vận dụng để thực hành trên máy tính Từ đó các em có thể làm tốt các đề bài
có dạng tương tự trong các kì thi chọn học sinh giỏi tin học
II Nội dung và giải pháp thực hiện
II.1 Nội Dung
I MỞ ĐẦU
Tư tưởng quy hạch động được Bellman đề cập từ 1960 nhằm tìm nghiệm của bài toán tối ưu Thời kỳ 1960-1970 là thời kỳ phát triển rực rỡ nhất của phương pháp này, nhờ nó nhiều bài toán với kích thước dữ liệu lớn hơn đã được giải với tốc độ chạy chương trình nhanh hơn so với những cách giải trước đây Song đến năm 1970
đã xuất hiện một số bài toán mới mà cách giải bằng quy hoạch động tỏ ra hạn chế, chỉ tương đối có hiệu quả, thậm chí có bài hầu như không có hiệu qủa Tuy nhiên với hàng loạt bài toán thông dụng phương pháp này vẫn là một trong các phương pháp tốt
1 Phương pháp giải các bài toán - tin bằng quy hoạch động (QHĐ)
Trong nhiều trường hợp, để giải một bài toán đã cho ta đưa về giải một số bài toán con rồi kết hợp nghiệm của các bài toán con để nhận được nghiệm của bài toán cần giải Để giải được các bài toán con này ta lại đưa về giải các bài toán con nhỏ hơn Quá trình trên sẽ tiếp tục cho tới khi nhận được các bài toán con có thể giải được dễ dàng, đó là kỹ thuật chia - để - trị, nó giải các bài toán con nhận được trong quá trình chia nhỏ một cách độc lập Phương pháp quy hoạch động cũng có những điểm giống
kỹ thuật chia để trị nhưng trong quá trình phân chia bài toán thành các bài toán con, các kết quả của mỗi bài toán con được lưu lại để xây dựng kết quả bài toán ban đầu
và tránh giải nhiều lần cùng một bài toán con Do đó phương pháp quy hoạch động thường giải bằng kỹ thuật dưới lên (bottom-up)
Trang 5Function ToHop(k, n : Integer) : Integer;
Begin
If (k=0) or (k=n) then ToHop:=1 Else ToHop:=ToHop(k,n-1)+ToHop(k-1,n-1);
End;
Với cách viết như trên thì có nhiều giá trị của tổ hợp được tính lại nhiều lần, chẳng hạn để tính ToHop(3,5) ta phải tính 2 lần ToHop(2,3); 3 lần ToHop(1,2), Do
đó thời gian tính toán sẽ rất lớn khi các giá trị đầu vào lớn
Để khắc phục hạn chế trên, ta dùng một mảng C[0 k,0 n] để lưu các kết quả đã tính, với mỗi i,j ta chỉ cần tính một lần Cji và lưu vào C[i,j] Mảng C được xây dựng theo nguyên tắc từ dưới lên với những nhận xét sau:
Trang 6Quy hoạch động là một phương pháp dựa vào kỹ thuật từ dưới lên Để giải bài toán, chúng ta thường xuất phát từ những trường hợp riêng đơn giản nhất của bài toán (thường là thấy ngay nghiệm của chúng) Nghiệm của bài toán trong những trường hợp cụ thể được lưu lại rồi kết hợp theo từng bước để nhận được nghiệm của bài toán có cỡ “lớn hơn” và cuối cùng là nhận được nghiệm của bài toán đã cho Do
đó khi giải một bài toán con ta chỉ cần tìm những nghiệm của các bài toán con có cỡ nhỏ hơn mà kết quả đã được giải và lưu trong bảng kết quả mà không cần giải lại Chính điều này làm cho các thuật toán quy hoạch động có hiệu quả cao
Để giải một bài toán bằng phương pháp QHĐ chúng ta phải tiến hành các bước
cơ bản sau:
Tìm nghiệm các bài toán con (các trường hợp riêng) của bài toán
Tìm công thức (hoặc quy tắc) xây dựng nghiệm của các bài toán con thông qua nghiệm của các bài toán con cỡ nhỏ hơn (gọi là công thức truy hồi)
Tổ chức cấu trúc dữ liệu hợp lý (thường là dạng bảng) để lưu giữ nghiệm của các bài toán con Sau đó tính nghiệm của các bài toán con theo công thức đã xây dựng ở bước trước và tiếp tục lưu vào bảng
Từ bảng các nghiệm của các bà toán con đã được làm đầy, tìm cách xây dựng lời giải cho bài toán
Các bước trên được liệt kê theo thứ tự nhưng để hình thành các bước này cho một bài toán cụ thể ta phải tổng hợp tất cả các bước, trong đó nhiệm vụ xây dựng công thức truy hồi xác định nghiệm (hoặc một thành phần của nghiệm) mới hình thành được cách giải chính xác Để minh họa, ta xét một số ví dụ sau :
Ví dụ 2 Dãy con tăng dài nhất
Cho N là một số nguyên dương (0<N<104 +1) và một dãy A1, A2 , ,An các số nguyên Hãy tìm trong dãy đã cho một dãy con Ai1, Ai2, , Aik không giảm và có
số phần tử lớn nhất
Trang 7Ý tưởng của thuật toán quy hoạch động ở đây là: Để xây dựng dãy con không giảm dài nhất của dãy đã cho chúng ta sẽ xây dựng dãy con không giảm dài nhất của đoạn
+ Với mỗi i >= 2 thì F[i] được tính bằng công thức truy hồi sau:
F[i]=Max{F[j]+1} với j=i-1, 1 mà aj < ai
Bây giờ chúng ta phải tìm vị trí i sao cho F[i] đạt max Ta lưu vị trí đó vào biến Luu Như vậy: F[Luu] chính là số lượng phần tử của dãy con cực đại của dãy đã cho Và bằng mảng Truoc ta có thể lấy lại chỉ số các phần tử thuộc dãy con đó
Đến đây ta gặp một vấn đề: Mảng Truoc chỉ cho phép ta lần ngược từ cuối về đầu dó
đó để in ra các chỉ số theo thứ tự tăng dần ta phải dùng thêm một mảng phụ P và in ngược lại của mảng P:
Trang 8Chỉ số theo thứ tự tăng dần của dãy con cực đại được in ra bằng dòng lệnh:
For i:=dem downto 1 do Write(P[i],' ');
Tuy nhiên làm như trên có vẻ dài dòng trong khi chúng ta đã nhận ra tính đệ quy trong việc lấy ngược lại Và thủ tục in ra dãy con đã rất ngắn gọn và sáng sủa:
Procedure Print(i:Integer);
Begin
If i>0 then Begin
Ta có toàn văn chương trình:
Trang 9for j:= i-1 downto 1 do
if (a[j] <= a[i]) and (b[j] > bmax) then
Trang 113) Sơ đồ giải bài toán QHĐ:
B1 Lập hệ thức: Lập hệ thức biểu diễn tương quan quyết định của bước đang
xử lý với các bước đã xử lý trước đó Hệ thức này thường là các biểu thức đệ quy do
đó dễ gây ra hiện tượng tràn miền nhớ khi ta tổ chức chương trình trực tiếp bằng đệ quy
B2 Tổ chức dữ liệu và chương trình: Tổ chức dữ liệu tính toán dần theo từng
bước Nên tìm cách khử đệ quy Thông thường, trong các bài toán chúng ta hay gặp đòi hỏi một vài mảng hai chiều
B3 Truy vết: tìm kết quả của bài toán tử bảng một chiều hoặc hai chiều đã xây
dựng
Trang 12Dưới đây là các ví dụ minh họa
Ví dụ 3: Bài toán Ba lô 1
Cho ba lô chứa được trọng lượng tối đa là w Có n đồ vật, đồ vật thứ i có khối lượng a[i] và giá trị c[i], 1<= i <=n Tìm cách xếp đồ vật vào ba lô sao cho đạt giá trị lớn nhất
B2 Tổ chức dữ liệu và chương trình: Giá trị lớn nhất là f(n,w) Ta dùng mảng
bản ghi a[1 n,1 w] chứa kết quả trung gian Mỗi bản ghi a[k,v] chứa giá trị f(k,v) và giá trị x thoả mãn công thức (*)
B3 Truy vết:
Trang 13Để xác định số lượng x[i] đồ vật i thoả mãn điều kiện tối ưu, ta xuất phát từ a[n,w] xác định được x[n] Nhảy tới a[n-1,w-x[n]*a[n]] xác định được x[n-1] Cứ như vậy tới x[1]
Sau đây là lời giải, chương trình được viết bằng ngôn ngữ Pascal:
Trang 14F[i,j]:=f[i-1,j];luu[i,j]:=0; (*Neu khong chon vat i *)
for k:=1 to j div a[i] do
(* Duyet het kha nang co the cho vat i tu 1 > k vat *)
if (F[i,j]< F[i-1,j-a[i]*k]+C[i]*k) then
(* Neu chon vat i vat so luong k ma gia tri lon hon chap nhan gia tri moi *) Begin
F[i,j]:=F[i-1,j-a[i]*k]+C[i]*k; (* ghi nhan gia trij F[i,j] *)
luu[i,j]:=k; (* Ghi nhan vat i da chon voi so luong la k *)
Trang 15n <- n-1 <- <- 1 khong dep lam *)
Trang 16Ví dụ 4: Bài toán ba lô 2: Cho ba lô chứa được trọng lượng tối đa là w Có n đồ vật,
đồ vật thứ i có khối lượng a[i] và giá trị c[i], 1<= i <=n Tìm cách xếp đồ vật vào ba
lô sao cho đạt giá trị lớn nhất (số lượng 1 vật có thể chọn 1 hoặc không chọn)
Trang 17Đặt: F[i,j]=max(F[i-1,j], F[i-1,j-a[i]]+C[i]) (*) ,với i=1,2, ,n, j=1=1,2 ,w
B2 Tổ chức dữ liệu và chương trình: Giá trị lớn nhất là F(n,w) Ta dùng mảng
bản ghi a[1 n,1 w] chứa kết quả trung gian Mỗi bản ghi luu[i,j] chứa giá trị F(i,j)
và giá trị x thoả mãn công thức (*)
B3 Truy vết:
Để xác định số lượng x[i] đồ vật i thoả mãn điều kiện tối ưu, ta xuất phát từ a[n,w] xác định được x[n] Nhảy tới luu[n-1,w-a[n]] xác định được x[n-1] Cứ như vậy tới x[1]
Sau đây là lời giải, chương trình được viết bằng ngôn ngữ Pascal:
Trang 18For i:=1 to n do (* duyet het cac vat tu 1 den n *)
For j:=1 to W do (* duyet het kich co tui tu 1 den w *)
Begin
if j>=a[i] then (* neu co tui lon hon vat i *)
if (F[i-1,j]< F[i-1,j-a[i]]+C[i]) then
(* neu chon vat i co gia tri lon hon khong chon no thi chap nhan *)
Begin
F[i,j]:=F[i-1,j-a[i]]+C[i]; (*ghi nhan gia tri F[i,j] *)
luu[i,j]:=1; (* ghi nhan vat i co chon *)
Trang 20Bài 1 Đổi tiền
Có n loại tiền có trị giá A1, A2, , An Hãy dùng các loại tiền này đổi số tiền L sao cho tổng số tờ tiền là ít nhất
Hướng dẫn :
Công thức truy toán:
Gọi F(L) là số tờ tiền ít nhất cần dùng để đổi được số tiền L
Ta có nhận xét :
Trang 211 F(Ai) = 1 với mọi i = 1, 2, , n
2 F(L) = Min{F(L-A1), F(L-A2), , F(L-An)}+1 nếu L <> Ai với mọi i
Tổ chức dữ liệu :
Dùng một mảng F có L phần tử, trong đó F[i] lưu giá trị của F(i) tính được
Dùng một mảng tối đa L phần tử để lưu các loại tiền ở mỗi bước chọn
Lưu ý : Nếu F[L] chưa được tính nghĩa là bài toán không có lời giải
Bài 2 Cho một hình tam giác các con số như hình vẽ Từ một con số bất kỳ, ta chỉ
có thể đi xuống qua con số bên trái hoặc bên phải ở hàng dưới Xuất phát từ đỉnh hình tam giác và đi xuống cho đến đáy hình tam giác Hãy tìm đường đi sao cho tổng các con số có được trên đường đi là nhỏ nhất/lớn nhất
Đặt: F[i,j]=max(F[i-1,j-1], F[i-1,j])+a[i] (*) ,với i,j=1,2, ,n
Smax = Max(F[n,j]) với i,j=1,2, ,n
Bài 3 Viết chương trình làm các việc sau :
1 Nhập từ bàn phím hai xâu ký tự S1 và S2
2 Ta có thể dùng một trong ba loại phép biến đổi sau:
BĐ1: xóa một ký tự nào đó trong xâu
BĐ2: thêm một ký tự nào đó vào vị trí bất kỳ trong xâu
BĐ3: thay một ký tự nào đó trong xâu bằng một ký tự khác
Trang 22Hãy thông báo ra file OUT.TXT liệu có thể dùng một số phép biến đổi thuộc
ba loại trên để biến đổi S1 thành S2 không, quy cách thông báo như sau: ví dụ
S1 = ‘ptslddf’, S2 = ‘tsgldds’, thì ta phải thông báo như sau :
Biến đổi được ptslddf -xóa p/1 => tslddf tslddf - thêm g/3 => tsglddf tsglddf - thay f/7/s => tsgldds
3 Trong trường hợp biến đổi được, hãy tìm một cách biến đổi dùng ít phép biến đổi nhất và thông báo tiếp vào file OUT.TXT theo quy cách như trên Hướng dẫn :
Giả sử độ dài của S1, S2 tương ứng là M và N Ta xây dựng mảng A[0 M,0 N] mà A[i,j] bằng số phép biến đổi ít nhất cần dùng để biến đổi đoạn đầu độ dài i của S1
thành đoạn đầu độ dài j của S2 Ta có A[0,j] = j và A[i,0]=i với 0<=i<=M và 0<=j<=M Việc tính A[i,j] dựa vào công thức đệ quy
A[i,j] = min {A[i,j-1]+1, A[i-1,j]+1, A[i-1,j-1]+T[i,j]}
với T[ị] = 0/1 tùy theo S1[i] bằng hay khác S2[j]
Bài 4 Hành trình con gián
Cho một lăng trụ tròn chu vi N đơn vị, chiều cao M đơn vị, được chia thành M
N ô bằng nhau, các vệt ô theo đường sinh được đánh số liên tiếp từ 1 đến N còn các vệt từ trên xuống dưới được đánh số liên tiếp từ 1 đến M Một con gián bò từ trên xuống dưới theo quy tắc sau : Khi đứng tại một cạnh của một ô, nó chỉ có thể chọn một trong 3 ô trước mặt, bên phải, bên trái để đi Mỗi ô [i,j] ghi một số nguyên dương A[i,j] biểu thị lượng thức ăn nó ăn được tại ô đó Hãy chọn cho con gián một hành trình từ trên xuống dưới của hình trụ để nó ăn được nhiều thức ăn nhất
Hướng dẫn :
Dùng mảng hai chiều B, trong đó B[i,j] là tổng chi phí nhỏ nhất để đi từ cột 1 (dòng xuất phát bất kỳ) tới ô [i,j]
Trang 23Công thức truy hồi : B[i,j] = A[i,j] + min(B[i-1,j-1], B[i,j-1], B[i+1j-1]}
Bài 5 Tiền kim loại
Giả sử một lúc nào đó bạn có N loại tiền kim loại (dạng đồng xu) được đánh số từ 1 đến N, mỗi loại có số lượng đồng không giới hạn Mỗi đồng của loại tiền kim loại thứ i mang giá trị vi xu và có trọng lượng wi gam Vì các loại tiền được đúc bằng các kim loại khác nhau nên có thể có những loại tiền cùng giá trị hoặc cùng trọng lượng nhưng không thể đồng thời có cả cùng giá trị và trọng lượng
Trong số N loại tiền của bạn, hãy chọn ra một số ít nhất M các đồng sao cho chúng
có tổng giá trị là V xu và tổng trọng lượng là W gam M sẽ nhận giá tị 0 nếu không
có cách chọn các đồng tiền thỏa mãn hai giá trị V và W
Ví dụ: Cho thông tin về N = 8 đồng tiền như sau:
Dữ liệu vào từ file COIN.IN có cấu trúc :
- Dòng đầu chứa 3 số tự nhiên N, V, W (1 <=N<=20; 1<=V,W<=150)
- N dòng tiếp theo, dòng thứ i chứa cặp số (vi, wi) là thông tin về một đồng của loại tiền thứ i (1<=vi, wi<=150)