Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 96 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
96
Dung lượng
373,04 KB
Nội dung
1
Lời nói đầu
Lập trìnhđộng (còn gọi là phương pháp quy hoạch động) là một kĩ thuật rất
hiệu quả giải quyết nhiều bài toán tin học, đặc biệt là những bài toán tối ưu. Số
lượng bài toán được giải bằng lậptrìnhđộng cũng rất lớn, ví dụ riêng kì thi
Olympic quốc tế về Tin học IOI 2004 có tới 3 bài trong 6 bài thi có thể giải bằng
lập trình động. Nhiều năm gần đây, trong hầu hết các đề thi chọn HSG QG đều
có ít nhất 1 trong 3 bài có thể giải bằng phương pháp quy hoạch động.
Nhóm tác giả chúng tôi biên tập tàiliệu “Bài tập quy hoạch động” này
mong muốn giới thiệu lí thuyết và các bài tập từ đơn giản đến phức tạp của lập
trình động. Cuốn sách sẽ là tàiliệu quí báu đối với học sinh năng khiếu Tin học,
sinh viên các ngành công nghệ thông tin và giáo viên môn Tin học của các
trường THPT.
Tài liệu gồm 4 chương:
Chương I: Cơ sở lý thuyết
Chương II: Một số bài tập cơ bản
Chương III: Bài tập chọn lọc
Chương IV: Một số đề tự giải
Chương I nêu rõ tư tưởng, vị trí, ứng dụng của lậptrìnhđộng và cách nhận
diện các bài tập có thể giải bằng phương pháp quy hoạch động. Chương II phân
tích và dẫn ra chương trình giải các bài toán kinh điển như: Tìm dãy con không
giảm dài nhất, Dãy con chung dài nhất, Tìm dãy con có tổng bằng S, ….Chương
III, chương IV giới thiệu đề bài, cách giải, chương trình của rất nhiều bài tập
chọn lọc.
Chúng tôi chân thành cảm ơn các bạn đồng nghiệp đã nhận xét và góp ý
cho bản thảo, trân trọng cảm ơn BGH trường THPT Chuyên Bắc Giang đã khích
lệ, tạo điều kiện cho nhóm tác giả được nghiên cứu để tàiliệu sớm được ra mắt
bạn đọc.
2
Trong quá trình biên soạn, mặc dù chúng tôi đã cố gắng, song nội dung
chuyên đề ngày càng có nhiều khía cạnh mới và sâu sắc nên chắc chắn tài liệu
còn nhiều hạn chế. Chúng tôi rất mong được bạn đọc xa gần góp ý, để lần tái bản
sau tàiliệu sẽ hoàn thiện hơn.
Mọi góp ý, xin gửi đến địa chỉ:
Nhóm Tin học Trường THPT Chuyên Bắc Giang
3
Chương I: Cơ sở lý thuyết
I.1. Tư tưởng của phương pháp quy ho ạch động
I.1.1. Thuật toán chia để trị
Lậ p trìnhđộng cũng như chia để trị là các phương pháp giải một bài toán
bằng cách tổ hợp lời giải các bài toán con c ủa nó.
Thuật toán chia để trị đượ c coi là thuật toán thông dụng nhất trong Tin
học. Khi giải một bài toán P với kích thước ban đầu nào đó nếu gặp trở ngại vì
kích thước quá lớn, người ta thường nghĩ đến việc giải các bài toán tương tự
nhưng với kích thước nhỏ hơn (gọi là các bài toán con của P). Tư tưởng “chia để
trị” thường được nhắc tới như hình ảnh “bẻ dần từng chiếc đũa để bẻ gãy cả
bó đũa”.
Chia để trị thực hiện “tách” một bài toán ban đầu thành các bài toán con
độc lập, sau đó giải các các bài toán con này và tổ hợp dần lời giải từ bài toán
con nhỏ nhất đến bài toán ban đầu.
Nhưng giải từ ng bài toán con như thế nào? Chúng ta có thể thực hiện một
cách đơn giản lại “tách” bài toán con thành các bài toán con nhỏ hơn nữa, và
cứ tiến hành như vậy cho đến khi gặp các bài toán con nhỏ đến mức dễ dàng
giải được. Các bài toán con cùng được sinh ra sau mỗi lần “tách” được gọi là
cùng mức. Những bài toán con sinh ra sau hơn thì ở mức dưới (thấp hơn).
Thủ tục đệ quy luôn là cách thường dùng và hiệu quả để thực hiện thuật
toán chia để trị. 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à sẽ thực hiện giải các bài toán con theo thứ tự ngược lại từ bài
toán đơn giản nhất trên đỉnh ngăn xếp cho đến khi giải được bài toán ban đầu
ở đáy ngăn xếp.
Ví dụ: Cho mảng a[1 n] gồm các số đã sắp tăng. Tìm phần tử của mảng có
giá trị bằng số x cho trước.
4
Xét chương trình thực hiện thuật toán tìm kiếm nhị phân (một kiểu chia
để trị rất phổ biế n) để giải bài toán trên. Trong chương trình chính có lời gọi
thủ tục tim(1,n). Sau đây là thủ tục tim(i,j):
Procedure tim(i,j : integer); {Tim x c ó trong mảng a[i j] hay không}
Var k : integer;
Begin
K := (i+j) div 2;
If a[k] = x then
Begin
Write(‘Co phan tu bang ‘,x);
Halt;
End
Else
If (a[k] < x) and (k<j) then tim(k+1,j)
Else
If (a[k] > x) and (k>i) then tim(i,k -1)
End;
Do chỉ tìm kiếm trên mộ t trong hai phần được “tách” ra, nên độ phứ c tạp
thuật toán là O(log
2
n), tốt hơn là tìm kiếm tuần tự.
I.1.2. Hệ thức truy hồi
Giải bài toán thường tiến hành theo nhiều bước. Kết quả của một bước
thường dựa vào kế t quả của các bước thực hiện trước đó. Do vậy, cần xây
dự ng hệ thức thể hiện quan hệ về kết quả giữa các bước gọi là hệ thức truy
hồi.
Ví dụ 1: Cho dãy số Fibonaci {F
1
, F
2
, …, F
n
}, trong đó:
F
1
= F
2
= 1 và F
n
= F
n-1
+ F
n-2
với n > 2 (1). Tìm số hạng thứ n.
5
Hệ thức tính số hạng thứ n củ a dãy Fibonaci là hệ thức (1) đã cho sẵn
trong đề bài.
Ví dụ 2: Cho một dãy N số nguyên A
1
, A
2
, …, A
n
. Hãy tìm cách xoá đi một số
ít nhất số hạng để dãy còn lại là đơn điệu hay nói cách khác hãy ch ọn một số
nhiều nhất các số hạng sao cho dãy B g ồm các số hạng đó theo trình tự xuấ t
hiện trong dãy A là đơn điệu.
Minh hoạ cho ví dụ 2:
Dãy A: 1, 4, 10, 9, 8, 1 7, 11, 7, 12, 6
Dãy B: 1,4,10,11,12
Phân tích để giả i bài toán ta thấy:
Khi dãy A có một phần tử a1thì dãy B có 1 phần tử .
Mở rộng bài toán với dãy A có 2 phần tử, có 3 phần tử, … để tìm độ dài
dãy B. Ta có bài toán tổng quát: Gọi F[i] là số phần tử của dãy con B khi dãy A
có các phần tử từ 1 đến i
Dễ dàng tính được:
F[i] := 1 nếu không tồn tại j:= 1 i-1 để A[j] < A[i]
F[i] := max{F[j], j=1 i -1 thoả mãn a[j] < a[i]} + 1; (2)
Như vậy, để giải bài toán ở ví dụ 2 ta phải tiến hành qua n bước. lời giải ở
bước i (i=1,2,…,n) ph ụ thuộc vào lời giải của i-1 bước trước đó. Hệ thức (2)
chính là hệ thức truy hồi của bài toán.
I.1.3. Lậptrìnhđộng là gì?
Lậ p trìnhđộng giống phương pháp chia để trị ở chỗ: lời giải của bài toán
được tổ hợp từ lời giải các bài toán con.
“Chia để trị” sẽ phân chia bài toán ban đầu thành các bài toán con độc lập
(sự phân chia có cấu trúc dạng cây), giải các bài toán con này thường bằng đệ
quy, sau đó tổ hợp lời giải của chúng để được lời giải của bài toán ban đầu.
6
Lậ p trìnhđộng (dynamic programming) cũng phân chia bài toán thành các
bài toán con, nhưng các bài toán con phụ thuộc nhau (hay dùng từ gối nhau
cũng được), mỗi bài toán con có thể tham chiếu tới cùng một số bài toán con
mức dưới (sự phân chia không có cấu trúc dạng cây xem hình 1).
Hình 1: Đồ thị bài toán con cho dãy Fibonacci. Đây không phải là một cấu
trúc cây mà là một đồ thị có hướng phi chu trình mô tả quan hệ giữa các bài
toán con gối nhau.
Nói rằng một bài toán có các bài toán con trùng nhau có nghĩa là mỗi bài
toán con đó được sử dụng để giải nhiều bài toán lớn hơn khác nhau. Ví d ụ,
trong dãy Fibonacci, F
3
= F
1
+ F
2
and F
4
= F
2
+ F
3
— khi tính mỗi số đều phải tính
F
2
. Vì tính F
5
cần đến cả F
3
và F
4
, một cách tính F
5
một cách ngây thơ có thể sẽ
phải tính F
2
hai lần hoặc nhiều hơn. Điều này áp dụng mỗi khi có mặt các bài
toán con gối nhau: một cách tiếp cận ngây thơ có thể tốn thời gian tính toán l ại
lời giải tối ưu cho các bài toán con mà nó đ ã giải.
Để tránh việc đó, ta lưu trữ lời giải của các bài toán con đ ã giải. Do vậy,
nếu sau này ta cần giải lại chính bài toán đó, ta có thể lấy và sử dụng kết quả
đã được tính toán. Hướng tiếp cận này được gọi là lưu trữ (trong tiếng Anh
được gọi là memoization, không phải memorization , dù từ này cũng hợp nghĩa).
Nếu ta chắc chắn rằng một lời giải nào đó không còn cần thiết nữa, ta có thể
xóa nó đi để tiết kiệm không gian b ộ nhớ. Trong một số trường hợp, ta còn có
thể tính lời giải cho các bài toán con mà ta bi ết trước rằng sẽ cầ n đến.
7
Khi giải bài toán Fibonaci cỡ i (với i tăng từ 2 đến n), ta đều sử dụng kết
quả của 2 bài toán con c ỡ i-1 và i-2;
Lậ p trìnhđộng do nhà toán học người Mỹ là Richard Bellman (1920-1984)
phát minh vào năm 1953.
Lậ p trìnhđộng thường dùng để giải các bài toán tối ưu – bài toán yêu cầu
tìm một giải pháp tốt nhất trong các giải pháp có thể tìm được.
Cơ sở của lậptrìnhđộng trong bài toán tối ưu là nguyên lí tối ưu Bellman:
“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ể 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ết tối ưu không phụ thuộc
vào trạng thái được sinh ra từ những quyết định ban đầu”
I.1.4. Phương pháp quy hoạch động
Trong ngành khoa h ọc máy tính, phương pháp 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 thể hiện các tính chất của
các bài toán con gối nhau và cấu trúc con tối ưu.
Tư tưởng chủ đạo của phương pháp quy hoạch động có thể tóm lược như
sau:
Chia 1 bài toán l ớn thành các bài toán con tương t ự có kích thước nhỏ hơn
cho đến khi nhận được các bài toán con mà l ời giải có thể xây dựng dễ dàng.
Ta phải tìm ra mối quan hệ giữa nghiệm của bài toán với nghiệm của các
bài toán con, mối quan hệ thể hiện 1 công thức truy hồi hay một hàm gọi là
công thức quy hoạ ch động (hay hàm quy ho ạch động).
Khi tính toán chúng ta xu ất phát tính từ nghiệm các bài toán con ban đ ầu,
sau đó kết hợp nghiệm của các bài toán con theo công th ức quy hoạch động ta
được nghiệm bài toán con có c ỡ lớn hơn. Quá trình cứ tiếp tục như vậy cho
đến khi ta được nghiệm của bài toán đã cho.
8
Vậy: Ý tưở ng cơ bản củ a quy hoạch động thật đơn giản: tránh tính toán
lại mọi thứ hai lần, mà lưu giữ kết quả đã tìm kiếm được vào một bảng làm giả
thiết cho việc tìm kiếm những kết quả của trường hợp sau. Chúng ta s ẽ làm
đầy dần giá trị của bảng này bởi các kết quả củ a những trường hợp trước đã
được giải. Kết quả cuối cùng chính là kết quả của bài toán cần giải
Ví dụ: Tính số hạng thứ n của dãy Fibonaci bằng phương pháp quy hoạch
động như sau:
Nghiệm của mỗi bài toán con chỉ cần tính 1 lần và được lưu trong mảng 1
chiều F. Khi tìm kết quả của các bài toán cỡ lớn hơn, kết quả của các bài toán
con chỉ việc lấy ra để sử dụng.
F1 := 1; F2 := 1;
For i := 3 to n do F [i] := F[i-2] + F[i-1];
I.2. Các bước thực hiện giải bài toán bằng phương pháp quy
hoạch động
I.2.1. Các bước cơ bản:
Bước 1: Phân tích tìm công th ức quy hoạch động
- Tìm ra công thức nghiệm của bài toán lớn thông qua việc giải các bài
toán con.
- Xác định nghiệm của bài toán con đơn giản (trong trường hợp cơ sở)
Bước 2: Thực hiện tính toán và tổ chức dữ liệu
- Đầu tiên tính nghiệm của bài toán con đơn giản (cơ sở)
(Khở i tạo giá trị ban đầu cho hàm QHĐ)
- Dựa vào hàm QHĐ đ ã xây dựng ta tính nghi ệm của bài toán theo kích
thước lớn dần cho đến khi nhận được nghiệm củ a bài toán đã cho.
Bước 3: Tổ chức dữ liệu và cài đặt
9
- Thường dùng mảng một chiều hoặc hai chiều để lưu trữ lại các giá trị
của các bài toán con (giá tr ị của hàm QHĐ)
- Ngoài ra, chúng ta ph ải dùng một số biến, thông thường cũng là mảng để
lưu trữ lại trạng thái của bài toán để sau này chúng ta có th ể truy xuất lời giải
của bài toán.
I.2.2. Tổ chức cài đặt:
- Có thể dùng vòng lặp
- Hoặc dùng đệ quy
- Nghiệm của các bài toán con đư ợc tính toán 1 lần và lưu trữ trong mảng
khi cầ n lấy ở mảng đó ra và sử dụ ng
I.2.3 Khi nào dùng phương pháp quy hoạch động?
- Khi gặp bài toán có tính ch ất truy hồi
- Khi lời giải bài toán ở bước sau được xây dựng thông qua lời giải bài
toán ở bước trước.
- Kích thước bài toán không quá l ớn
*Ưu điểm:
- Lời giải ngắn gọn, sang sủa, có tính logic cao, chương tr ình chạy nhanh.
*Nhược điểm:
- Không phải bài nào cũng giải bằng QHĐ
- Việc tìm ra công th ức QHĐ của nhiều bài toán là khó khăn
- Không có công th ức chung
- Bị hạ n chế về bộ nhớ vì chúng ta ph ải lưu trữ nghiệm của các bài toán
con.
10
Chương II: Một số bài tập cơ bản
Bài 1: Tìm dãy con không gi ảm nhiều phần tử nhất;
Cho dãy số nguyên có n ph ần tử a
1
, a
2
, …, a
n
. Một dãy con không gi ảm của
dãy đã cho là dãy các ph ần tử còn lại của dãy đó sau khi ta xóa b ỏ một hoặc
một số phần tử bất kì của nó, các phần tử của dãy con tạo thành dãy không
giảm. Ví dụ: dãy 1,4,10,11,12 là m ột dãy con không giảm của dãy 1, 4, 10, 9, 8,
17, 11, 7, 12, 6.
Yêu cầu: Tìm dãy con không gi ảm củ a dãy a gồm nhiều phần tử nhất.
Dữ liệu: Vào từ file văn bản DAYCON.INP gồm:
Dòng đầu tiên ghi số N (0 < N < 10
5
).
Các dòng tiếp theo, mỗi dòng ghi 10 s ố nguyên của dãy N số nguyên a
1
, a
2
,
, a
n
. Dòng cuối cùng có thể ít hơn 10 số. Các số trên một dòng cách nhau m ột
dấu cách.
Kết quả: Ghi ra file văn bản DAYCON.OUT g ồm:
Số max là độ dài dãy con không gi ảm dài nhất tìm được.
Chỉ số xuất hiện của các số hạng củ a dãy con trong dãy đã cho.
Ví dụ:
DAYCON.INP
DAYCON.OUT
10
6 5 8 12 6 9 7 13 2 13
5
2 5 7 8 10
Hướng dẫn:
Gọi L(i) là độ dài dãy con tăng dài nhất, các phần tử lấy trong miền từ a
1
đến a
i
và phần tử cuối cùng là a
i
.
Ta có công thức QHĐ để tính L(i) như sau:
L(1) = 1
L(i) = max(1, L(j)+1 v ới mọi phần tử j: 0 < j < i và a
j
≤ a
i
).
[...]... ế ề ằng cách xóa đi mộ ố ố ạ ứ ự ữ ồ ố ả Ghi ra file văn bả ố đầ ấ ố lượ ố ạ ủ ế ố ế ố ạ ứ ủ ứ ố ạ ứ ố ủ ớ ố ạ ứ ủ Ví dụ: *Hướng dẫn: ọi L(i,j) là độ ầ đầ ủ ấ ồ ủ ầ ồ ử ần đầ ầ ủ ử ứ ạch động như sau: ế ế *Chương trình cài đặt: Bài 3: Dãy con có tổng bằng S ộ ữ ệ ừ ă ứ ă ử ụ * Hướ ạ ố ả ầ ả đó có tổ ố đầ ế ủ ẫ ộ ả ạ đượ ằ ế Đặ ầ ử ể ạ Ngượ ể * Chương tr ổ ạ ộ ế ứ đặ ừ ủ ồ đáp án củ ế ặ Bài 4: Xếp...ảng phươ ộ ả ộ ị ủ QHĐ L(i) Đoạn chương tr Như vậ * Chương trình cài đặt: ều L để lưu trữ ủ ị ủa hàm ảng L như sau: ờ Bài 2: Dãy con chung dài nhất; ố ớ ộ ủ ấ ận đượ ận đượ ữ ệ ằng cách xóa đi mộ ố ố ạ ố ạ ủ ạ ầ ử ủ ừ file văn bả ở ấu trúc như sau: ố nguyên dương... trị có ọ ậ ều để lưu bảng phương án, tuy nhiên dự ủ ề ế ảng phương án chỉ ầ ỉ ố ừ 0 đến m để lưu 2 d ảng phương án như sau ỉ đó Đoạn ớ ếu để ọ ạ ẽ QHĐ chứ chưa tối ư ớ chương tr ị ối ưu hơn ờ *Chương trình cài đặt: ấ ằng đoạ ẳ ạn đ ỉ ế ố ức ệnh gán P:=L, sau đó lạ ầ ế ạn đọ ủa cách cài đặ ể ự ả ến để Chương III: Bài tập chọn lọc Bài 5: Bố trí phòng họp; ộ ọp đánh số ừ 1 đến n đăng ký l ọ ần đượ ả... dương n (n . bằng lập trình động cũng rất lớn, ví dụ riêng kì thi
Olympic quốc tế về Tin học IOI 2004 có tới 3 bài trong 6 bài thi có thể giải bằng
lập trình động. . thiệu lí thuyết và các bài tập từ đơn giản đến phức tạp của lập
trình động. Cuốn sách sẽ là tài liệu quí báu đối với học sinh năng khiếu Tin học,
sinh viên