Tải bản đầy đủ (.doc) (17 trang)

Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi dưỡng học sinh giỏi tin học 11.

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 (200.79 KB, 17 trang )

SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
I. MỞ ĐẦU
I.1.1/ LÝ DO CHỌN ĐỀ TÀI
- Ngày nay cùng với sự phát triển của đất nước, công nghệ thông tin đang đóng một vai
trò hết sức quan trọng, tác động đến hầu hết các lĩnh vực của đời sống xã hội. Việc đào
tạo một thế hệ tương lai có một sự phát triển toàn diện đòi hỏi ngành giáo dục luôn phải
có sự quan tâm đúng mức là điều rất cần thiết để có một nguồn nhân lực đáp ứng yêu
cầu CNH, HĐH mở cửa và hội nhập hướng tới nền kinh tế tri thức của nước ta nói riêng
và thế giới chung.
- Tin học là một môn học mới, việc truyền đạt kiến thức cơ bản trong sách giáo khoa đã
là khó khăn, làm sao để dạy học bồi dưỡng học sinh khá giỏi. Giúp các em không chỉ
nắm được những kiến thức cơ bản mà còn hiểu và giải quyết được những bài toán đòi
hỏi những thuật toán phức tạp hơn: Hoán vị, tổ hợp,tham lam,chia để trị,..đó là việc
khiến các giáo viên phải luôn luôn trăn trở và tìm những phương pháp phù hợp.
- Một thuật toán chỉ giải được một bài toán, nhưng một bài toán lại có thể có rất nhiều
thuật toán khác nhau. Làm thế nào để tìm ra thuật toán phù hợp, nhanh gọn, dễ hiểu, tốn
ít dung lượng bộ nhớ. Phương pháp quy hoạch động là một phương pháp hay, có nhiều
ưu điểm nhưng cũng có nhược điểm đó là khó tìm được công thức truy hồi. Ngoài ra
kiến thức mới cũng làm học sinh khó hấp thụ. Cách giải những bài toán phức tạp nhưng
dùng những kiến thức cũ đôi khi giúp học sinh dễ hiểu hơn. Từ những lí do trên tôi đã
quyết định chọn đề tài “sử dụng phương pháp quy hoạch động để giải một số bài toán
nhằm bồi dưỡng học sinh giỏi tin học 11”
I.1.2/ MỤC ĐÍCH NGHIÊN CỨU ĐỀ TÀI
- Mục tiêu chính của đề tài là nghiên cứu về pháp Quy Hoạch Động để giải một số bài
toán nhằm bồi dưỡng học sinh giỏi tin học 11.
- Giúp cho việc ôn thi học sinh giỏi tin học thi đạt kết quả ngày càng cao.
- Tạo ra nguồn tài liệu tham khảo về phương pháp cũng như thuật toán nhằm hỗ trợ cho
học sinh, giáo viên dạy bồi dưỡng học sinh giỏi tin học 11.
I.1.3/ ĐỐI TƯỢNG NGHIÊN CỨU VÀ PHẠM VI NGHIÊN CỨU
* ĐỐI TƯỢNG NGHIÊN CỨU


- Sử dụng phương pháp quy hoạch động và một số bài toán
- Học sinh giỏi tin học khối 11, Giáo viên giảng dạy học sinh giỏi tin học 11
* PHẠM VI NGHIÊN CỨU ĐỀ TÀI
- Sử dụng phương pháp quy hoạch động để giải một số bài toán bồi dưỡng học sinh giỏi
tin học 11.
I.1.4 PHƯƠNG PHÁP NGHIÊN CỨU TÀI LIỆU
- Thu thập, phân tích các tài liệu và thông tin liên quan đến quy hoạch động
- Lựa chọn 1 số bài toán để sử dụng phương pháp quy hoạch động.
1


SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
- Thiết kế các bài toán đã được lựa chọn trong chương trình tin học 11 để bồi dưỡng học
sinh giỏi bằng phương pháp quy hoạch động.
- Dùng ngôn ngữ lập trình turbo Pascal hoặc Free pascal để cài đặt bài toán và chạy
thử nghiệm trên một số bộ test để đánh giá kết quả.
II/ NỘI DUNG SÁNG KIẾN KINH NGHIỆM
II.2.1/ CƠ SỞ LÝ LUẬN:
+ Luật giáo dục nước ta đã cụ thể hoá tại chương II, mục 2 điều 23 là: “Mục tiêu của
giáo dục phổ thông là giúp học sinh phát triển toàn diện về đạo đức, trí tuệ, thể chất,
thẩm mỹ và các kỹ năng cơ bản nhằm hình thành nhân cách con người Việt Nam xã hội
chủ nghĩa, xây dựng tư cách và trách nhiệm công dân, chuẩn bị cho học sinh tiếp tục
học lên hoặc đi vào cuộc sống lao động tham gia xây dựng và bảo vệ Tổ Quốc”.
+ Môn tin học, cũng như mọi môn học khác, căn cứ vào mục tiêu trên để xác định nhiệm
vụ cụ thể của môn học, tổ chức hoạt động đào tạo góp phần thực hiện mục tiêu giáo dục
mà Đảng và nhà nước đề ra.
+ Ngoài việc tạo điều kiện cho học sinh chiếm lĩnh những tri thức và kỉ năng Tin học cần
thiết, Tin học còn có tác dụng phát triển năng lực trí tuệ chung như: phân tích, tổng hợp,
trừu tượng hoá, khái quát hoá…rèn luyện những đức tính, phẩm chất của người lao

động mới. Học sinh sẽ thấy rõ hiệu quả mạnh mẽ của công nghệ thông tin và nhận thức
cần có.
II.2.2/ THỰC TRẠNG VẤN ĐỀ CỦA SÁNG KIẾN KINH NGHIỆM
A*.Thực trạng chung:
Hiện nay nhu cầu xã hội đang rất cần những kĩ sư Công Nghệ Thông tin có trình
độ cao. Tuy nhiên việc đào tạo và bồi dưỡng học sinh yêu thích môn Tin học ở trường
Phổ thông hiện nay đang gặp rất nhiều khó khăn.
Tin học 11 là một môn học mới, để học tốt được lập trình đòi hỏi học sinh phải có
một kiến thức cơ bản tốt, phải có khả năng tư duy và niềm đam mê, ngoài ra học sinh
phải có điều kiện thực hành thường xuyên.
Đa số các em học sinh tập trung học các môn khối để ôn thi THPT Quốc Gia nên
không dành được nhiều thời gian cho môn Tin học. Trường đã có máy tính để thực hành
nhưng số lượng ít chưa đủ để tất cả các tiết thực hành đều được đáp ứng. Tài liệu tham
khảo dành cho môn tin học chưa có nhiều nên việc tiếp cận với những kiến thức mới còn
gặp nhiều khó khăn. Đó là cũng thực trạng chung của hầu hết các trường phổ thông hiện
nay.
B* Một số thuận lợi và khó khăn khi thực hiện đề tài ở trường THPT Tĩnh Gia I.
1. Thuận lợi:
* Nhà trường:
Trường THPT Tĩnh Gia 1 là ngôi trường có truyền thống với bề dày 54 năm. Là
trường chuẩn quốc gia nên trường cũng là nơi có điều kiện cơ sở vật chất tương đối đảm
bảo đáp ứng cho điều kiện học tập. Nhà trường đã tạo điều kiện để học sinh có điều kiện
2


SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
tốt nhất để học, tạo điều kiện về máy móc, trang thiết bị phục vụ cho việc dạy và học
môn Tin học.
* Học sinh:

Là môn học có tính ứng dụng cao nên đa số học sinh có ý thức tìm hiểu về môn
học nói riêng và CNTT nói chung. Một số học sinh có khả năng phát triển về lập trình và
yêu thích lập trình. Có nhiều gia đình đã có máy vi tính nên các em cũng có điều kiện
thực hành.
2. Khó khăn:
* Nhà trường:
Nhà trường đã có hai phòng máy vi tính để cho học sinh học nhưng vẫn còn hạn
chế về số lượng cũng như chất lượng, mỗi ca thực hành có tới 2 – 3 em ngồi cùng một
máy nên các em không có nhiều thời gian để thực hành làm bài tập một cách đầy đủ. Tuy
đã có hai phòng thực hành nhưng số lớp nhiều (30 lớp học) và mỗi lớp số lượng học sinh
khoảng 40 - 45 học sinh, tất cả các lớp đều học buổi sáng, tiết học thực hành cũng nằm
trong phân phối chương trình với các tiết khác nên không thể tránh khỏi việc chồng chéo
trong việc đăng kí lịch thực hành giữa các lớp.
* Giáo viên:
Đa số các giáo viên đều còn trẻ nên còn chưa có nhiều kinh nghiệm. Môn tin học mới
đưa vào giảng dạy nên giáo viên thường gặp khó khăn về phân hoá học sinh và bồi
dưỡng học sinh yêu thích và học khá giỏi môn tin. Do đó việc lựa chọn học sinh giỏi là
rất khó khăn vì học sinh giỏi thường học tốt các môn tự nhiên.
* Học sinh:
Có nhiều học sinh có kiến thức cơ bản tốt và có tư duy nhưng các em lại không có máy
tính thực hành ở nhà hoặc chỉ dành thời gian cho các môn khối mà không chọn vào đội
tuyển thi học sinh giỏi môn Tin. Học sinh đa số chưa tiếp cận ngôn ngữ lập trình nên rất
khó khăn trong học lập trình. Các bài toán sử dụng phương pháp quy hoạch động
thường khó lại là kiến thức mới ngoài sách giáo khoa nên học sinh khó tiếp cận và thực
hiện.
III/ GIẢI PHÁP VÀ TỔ CHỨC THỰC HIỆN.
- Học sinh được bồi dưỡng thi học sinh giỏi không chỉ cần nắm vững kiến thức trong
sách giáo khoa mà còn phải có khả năng tư duy tốt để giải quyết các bài toán khó. Việc
dạy học không chỉ là truyền đạt kiến thức cho các em mà giáo viên còn phải kích thích
sự sang tạo, niềm đam mê, sự say mê học hỏi và muốn tìm hiểu cái mới.

Phương pháp quy hoạch động dùng để giải bài toán tối ưu có bản chất đệ quy, tức là để
tìm phương án tối ưu cho bài toán nào đó có thể đưa về tìm phương án tối ưu của một số
hữu hạn các bài toán con.
- Phương pháp quy hoạch động là một kỹ thuật nhằm đơn giản hoá việc tính toán các
công thức truy hồi bằng cách lưu toàn bộ hay một phần kết quả tính toán tại mỗi bước
trước đó với mục đích sử dụng lại.
3


SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
Như vậy, Quy hoạch động = Chia để trị + Mảng (lưu lại kết quả).
- Phương pháp quy hoạch động do nhà toán học người Mỹ Richard Bellman ( 1920 –
1984) phát minh năm 1953. Phương pháp này dung để giải các bài toán tối ưu có bản
chất đệ qui, tức là tìm phương pháp tối ưu cho bài toán đó có thể đưa về tìm phương án
tối ưu cho bài toán đó có thể đưa về tìm phương án tối ưu của một số hữu hạn các bài
toán.
- Điểm khác nhau cơ bản giữa quy hoạch động và phương pháp đệ quy là:
+ Phương pháp đệ quy giải quyết bài toán theo hướng TOP _ DOWN, nghĩa là để
giải bài toán ban đầu, ta phải đi giải tất cả các bài toán con của nó. Đây là một phương
pháp hay, tuy nhiên phương pháp này sẽ gặp hạn chế về mặt thời gian, tốc độ do phải
tính đi tính lại nhiều lần một số bài toán con giống nhau nào đó.
+ Phương pháp quy hoạch động sử dụng nguyên lý Bottom – up, nghĩa là “ đi từ dưới
lên”. Đầu tiên, ta sẽ phải giải các bài toán con đơn giản nhất, có thể tìm ngay ra
nghiệm. Sau đó kết hợp các bài toán con này lại để tìm lời giải cho bài toán lớn hơn và
cứ như thế cho tới khi giải được bài toán yêu cầu. Với phương pháp này, mỗi bài toán
con sau khi giải xong đều được lưu trữ lại và đem ra sử dụng nếu cần. Do đó tiết kiệm
được bộ nhớ và cải thiện được tốc độ.
+QHĐ có ưu điểm là chương trình thực hiện nhanh do không phải tốn nhiều thời gian
để giải lại các bài toán con đã được giải.

- Công thức phối hợp nghiệm của các bài toán con để có nghiệm của các bài toán lớn
gọi là công thức truy hồi của quy hoạch động
- Không gian lưu trữ lời giải các bài toán con để tìm cách phối hợp chúng gọi là bảng
phương án của quy hoạch động
- Tạo bảng trong quy hoach động bằng cách:
+ Gán giá trị cho 1 số ô nào đó.
+ Giá trị cho các ô khác nhờ vào giá trị của các ô trước đó.
+ Tra bảng và xác định kết quả của bài toán ban đầu
- Quy hoạch động thường dùng một trong 2 cách tiếp cân:
+ Tiếp cận từ dưới lên (bottom up)
+ Tiếp cận từ trên xuống (top down)
Tôi xin giới thiệu một số bài toán có thể sử dụng phương pháp quy hoạch động giúp học
sinh dễ hiểu hơn, nó cũng là một cách để chúng ta so sánh các cách giải 1 bài toán và
nâng cao khả năng tư duy của học sinh.

Ví dụ 1: Tìm số fibonaci thứ n.

4


SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
Mô tả cây nhị phân tìm kiếm số Fib(4) theo phương pháp chia để trị có dạng cây như
sau:
F(5) =F(4)+ F(3)

F(4) =F(3)+ F(2)
F(3) =F(2)+ F(1)

F(3) =F(2)+ F(1)


F(2) =1
F(2) = 1

F(2) =1

F(1) = 1

F(1) =1

Để tính được F(5) ta phải gọi F(4) và F(3), tính được F(4) phải gọi F(3) và F(2),
F(1) và F(2) đã cho từ ban đầu.
BẢNG GIÁ TRỊ CỦA FIBONACI
I

0

1

2

3

4

5

6

7


8

9

10

F[i]

0

1

1

2

3

5

8

13

21

34

55


Chương trình minh họa
Function Fib(n:integer):longint;
Begin
IF n=0 THEN fib:=0 else
If n=1 then fib:=1 else
If n=2 then fib:=1
Else fib:=fib(n-1)+ fib(n-2);
End;
Begin
Readln(n);
Writeln(Fib(n));
End.
Cách 2: Phương pháp quy hoạch động
Ta sử dụng mảng S[0..MaxN], S[i] để lưu lại lời giải cho bài toán tính số Fibonacci thứ i
const
MaxN =
1000;
var
s: array[0..MaxN] of int64;
n, k: longint;
function
f(n:longint) :
int64;
Begin
if
s[n]=-1 then
5



SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
begin
if n< = 1then s[n] := n
else
s[n] := f(n-1) + f(n-2);
end;
f := s[n];
end;
begin
readln(n);
for k:=0
to
MaxN
do
writeln(f(n));
readln;
end.

s[k]:=-1;

* Hoặc ta có thể làm như sau
const
MaxN=
1000;
var
s: array[0..MaxN]
of
int64;
n,

i:
longint;
begin
readln(n);
s[0]:=0;
s[1]:=1;
for i:=2
to
n
s[i]
:=
s[i-1] + s[i-2];
Writeln(s[n]);
Readln;
End.

do

Trong cách giải thứ nhất để tìm ra số fibonaci thứ n ta phải tính tất cả các giá trị
trước đó. Tuy nhiên các giá trị tính toán trước đó không được lưu lại. Đối với cách giải
thứ 2 tất cả các giá trị được lưu trong mảng A nên khi cần sử dụng lại những giá trị
trước đó máy tính sẽ không phải tính lại. Để thấy rõ hơn ưu nhược điểm của 2 cách ta
xét ví dụ 2.
Ví dụ 2: Tính tổng 2 số fibonaci thứ n và thứ (n -2).
- Nếu dùng cách giải chia để trị ta có thể tính tổng rất nhanh bằng cách gọi 1 lời gọi
trong chương trình chính:
Tong:=fib(n)+ fib(n-2);
Tuy nhiên với lời gọi trên thì máy tính sẽ phải tính n + (n-2)=2n-2 phép toán.
Trong khi nếu dùng phương pháp quy hoạch động như trong cách 2 ví dụ 1
Ta chỉ cần tính: Tong:=a[n]+a[n-2];

Với phương pháp này các giá trị đã được lưu vào mảng nên máy tính chỉ phải tính 1 lần
và số phép tính thực hiện là: n.
VÍ DỤ 6:BÀI TOÁN TÍNH SỐ TỔ HỢP CHẬP K CỦA N PHẦN TỬ
6


SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
k

- Tìm các phần tử của mảng C[n,k] = C n = số tổ hợp chập k của n phần tử. với
0 ≤ k ≤ n ≤ 20
0

n

n

n

k

k −1

n

n −1

=C
C

Biết rằng:
C =C

=1
k

+ C n −1

Ý tưởng bài toán:
Bài toán trên cho ta gợi ý về thuật toán đệ quy như sau.
Function C(n,k:Longint):longint;
Begin
If (k=0) or (n=0) then c:=1 else C:=C(n-1,k-1) + C(n-1,k);
End;
Gọi T là thời gian để tính số tổ hợp chập k của n thì ta có phương trình đệ quy như
sau
T(1) =C1 và T(n)=2T(n-1) + C2.
Giải phương trình này ta được T(n) = O(2n) Như vậy là một giải thuật thời gian mũ,
Trong khi chỉ có một đa thức các bài toán con. Điều đó chứng tỏ rằng có những bài
toán con được giải nhiều lần.
Chẳng hặn như tính C(4,2) thì ta phải tính C(3,1) và C(3,2). Tính C(3,1) thì phải tính
C(2,0) và C(2,1). Tính C(3,2) thì phải tính C(2,1) và C(2,2). Như vậy để tính C(4,2)
thì phải tính C(2,1) 2 lần.
Hình minh họa
C(4,2)

C(3,1)
C(3,2)

C(2,0)


C(2,1)
C(2,1)

C(2,2)

Để khắc phục được việc tính toán lập đi lập lại nhiều lần ta có thể sử dụng thuật toán
quy hoạch động như sau
- Ta xây dựng một bảng gồm n+1 dòng (từ 0 đến n) và n+1 cột( từ 0 đến n) và
điền giá trị cho C(i,j) theo quy tắc như sau:
C(0,0) =1;
C(i,0)=1;
7


SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
C(i,i)=1 Với i> 0;
C(i,j) = C(i-1,j-1) + C(i-1,j) với 0Chẳng hặn ta có n=4 được biểu diễn như sau:
I

j

0

1

2


3

0

1

1

1

1

2

1

2

2

3

1

3

3

1


4

1

4

6

4

4

1

Chương trình minh họa
var n,k:longint;
C:array[0..1000,0..1000] of longint;
function tohop(n,k:longint):longint;
var
i,j:integer;
begin
C[0,0]:=1;
For i:=0 to n do
begin
C[i,i]:=1;C[i,0]:=1;
For j:=1 to i-1 do
C[i,j]:=C[i-1,j-1] + C[i-1,j];
end;
tohop:=C[n,k];
end;

begin
Writeln('nhap n,k:'); readln(n,k);
Writeln(tohop(n,k));
readln;
end.
n

Nếu gọi T là thời gian thực hiện giải thuật thì ta có T(n)=

∑ (i − 1) =
i =1

n(n − 1)
= O(n2).
2

Từ đó ta thấy sử dụng thuật toán quy hoạch động hiệu quả hơn nhiều so với thuật toán
đệ quy.
Ví dụ 4: BÀI TOÁN CÁI TÚI
Trong siêu thị có n gói hàng (n ≤ 100), gói hàng thứ i có trọng lượng là W i ≤ 100 và trị
giá Vi ≤ 100. Một tên trộm đột nhập vào siêu thị, sức của tên trộm không thể mang
8


SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
được trọng lượng vượt quá M (M ≤ 100). Hỏi tên trộm sẽ lấy đi những gói hàng nào để
được tổng giá trị lớn nhất.
Input: File văn bản Tui.inp
+ Dòng 1:chứa 2 số n ,M cách nhau ít nhất 1 dấu cách.

+ n dòng tiếp theo mỗi dòng gồm 2 số Vi ,Wi , là chi phí và giá trị đồ vật thứ i.
Output: đưa ra màn hình những gói hang có tổng giá trị lớn nhât
VD: input

5 15

output: 15

12 4
2 2
1 1
1 2
4 10
Ý tưởng giải bài toán
- Nếu gọi B[i, j] là giá trị lớn nhất có thể có bằng cách chọn trong các gói {1 ..., i} với
giới hạn trọng lượng j. Thì giá trị lớn nhất khi được chọn trong số n gói với giới hạn
trọng lượng M chính là B[n, M].
- Với giới hạn trọng lượng j, việc chọn tối ưu trong số các gói {1,..,i} để có giá trị lớn
nhất sẽ có hai khả năng:
• Nếu không chọn gói thứ i khi đó giá trị lớn nhất sẽ là B[i, j] = B[i - 1, j]
• Nếu có chọn gói thứ i (mà Wi ≤ j) khi đó giá trị lớn nhất có thể là: B[i, j] = Vi + B[i 1, j - Wi].Vì theo cách xây dựng B[i, j] là giá trị lớn nhất có thể nên nó sẽ là max trong
2 giá trị thu được ở trên.
- Dễ thấy B[0, j] = giá trị lớn nhất có thể bằng cách chọn trong số 0 gói = 0.
- Bảng phương án B gồm n + 1 dòng, M + 1 cột, trước tiên được điền cơ sở quy hoạch
động: Dòng 0 gồm toàn số 0. Sử dụng công thức truy hồi, dùng dòng 0 tính dòng 1,
dùng dòng 1 tính dòng 2,.... đến khi tính hết dòng n.
Từ ví dụ trên ta có bảng phương án sau.
N/
0
1

2
3
4
5
6
7
8
9
10 11 12 13 14 15
M
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0

0
0
0
0
0
0
0
0
0
0
4
4
4
4
2
0
0
2
2
2
2
2
2
2
2
2
2
4
4
6

6
3
0
1
2
3
3
3
3
3
3
3
3
3
4
5
6
7
4
0
2
3
4
5
5
5
5
5
5
5

5
5
6
7
8
5
0
2
3
4
10 12 13 14 15 15 15 15 15 15 15 15
Vậy ta có thể chọn gói 5,4,3,2.
9


SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
Tính xong bảng phương án thì ta quan tâm đến b[n, M] đó chính là giá trị lớn
nhất thu được khi chọn trong cả n gói với giới hạn trọng lượng M. Nếu b[n, M] = b[n 1, M] thì tức là không chọn gói thứ n, ta truy tiếp b[n - 1, M]. Còn nếu b[n, M] ≠ b[n 1, M] thì ta thông báo rằng phép chọn tối ưu có chọn gói thứ n và truy tiếp b[n - 1, M Wn]. Cứ tiếp tục cho tới khi truy lên tới hàng 0 của bảng phương án.
Chương trình minh họa
Const max = 1000;
var
W, V: Array[1..max] of integer;
B: array[0..max, 0..max] of integer;
n, M: integer;
f1:text;
procedure
Nhap;
var
i: Integer;

begin
assign(f1,'tui.inp'); reset(f1);
read(f1,n,M);
for i := 1 to n do
readln(f1,W[i],V[i]);
close(f1);
end;
procedure
tinh;
var
i, j: Integer;
begin
FillChar(B[0], SizeOf(B[0]), 0);
for i := 1 to n do
for j := 0 to M do
begin
B[i, j] := B[i - 1, j];
if (j >= W[i]) and (B[i, j] < B[i - 1, j - W[i]] + V[i])
then
B[i, j] := B[i - 1, j - W[i]] + V[i];
end;
end;
procedure Truy_timnghiem;
begin
writeln('gia tri max la:',B[n,M]);
while n <> 0 do
begin
if B[n, M] <> B[n - 1, M] then
begin
writeln('goi thu',n,'w=',w[n],'v=',v[n]);

M := M - W[n];
10


SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
end;
Dec(n);
end;
end;
begin
Nhap;
Tinh;
Truy_timnghiem;
readln;
end.
Ví dụ 5: BÀI TOÁN XẾP BA LÔ
Có một ba lô có thể chứa tối đa trọng lượng M và có n đồ vật (n <= 100), mỗi đồ vật
có trọng lượng Wi và giá trị bi. M, Wi, bi, là các số nguyên. Hãy chọn và xếp các đồ vật
vào ba lô để tổng giá trị của ba lô là lớn nhất.
Với bài toán trên ta thấy:
- Hàm mục tiêu : ∑bi  max, i=1,2,3,…,n
- Hàm ràng buộc ∑Wi ≤ M, i = 1,2,…,n
Ý tưởng giải bài toán:
- Sử dụng mảng A[0..n,0..M] để lưu trữ lại các giải pháp giải các bài toán con.
- Gọi A[i,j] là tổng giá trị lớn nhất của ba lô mà trọng lượng không vượt quá j khi
sử dụng các đồ vật { 1,2,…,i} khi đó giá trị lớn nhất khi được chọn trong số n gói
với giới hạn trọng lượng M chính là A[n,M].
- Với giới hạn trọng lượng j, việc chọn tối ưu trong số các gói {1,2,…,i-1,i} để có
giá trị lớn nhất sẽ có 2 khả năng:

+ Nếu không chọn gói thứ i thì A[i,j] là giá trị lớn nhất có thể bằng cách chọn
trong số các gói {1,2,…,i-1} với giới hạn trọng lượng là j tức là A[i,j] = A[i-1,j].
+ Nếu có chọn gói thứ i (khi Wi ≤j) thì A[i,j]=bi + A[i-1, j- Wi]
Ban đầu
A[0,i] = 0 với i
A[0,i] = 0 với mọi i.
Sau đó A[i,j] sẽ tính theo A[i-1,j] hoặc A[i-1,j-Wi].
Chương trình minh họa
uses crt;
var A:array[0..1000,0..1000] of longint;
W,b:array[1..1000] of longint;
N,M,i,j:longint;
f1,f2:text;
11


SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
begin
clrscr;
assign(f1,'balo.inp'); assign(f2,'balo.out'); reset(f1); rewrite(f2);
readln(f1,N,M);
for i:=1 to N do read(f1,W[i]);
for i:=1 to N do read(f1,b[i]);
for i:=1 to N do A[i,0]:=0;
for i:=1 to M do A[0,i]:=0;
for j:=1 to M do
for i:=1 to N do
Begin
if (j-W[i]>=0) and (b[i]+A[i-1,j-W[i]]>A[i-1,j]) then A[i,j]:=b[i]+A[i-1,j-W[i]];

if (j-W[i]<0) or (b[i]+A[i-1,j-W[i]]<=A[i-1,j]) then A[i,j]:=A[i-1,j];
end;
for j:=1 to M do begin for i:=1 to N do write(f2,A[i,j],' ');
writeln(f2);
end;
close(f1);close(f2);
end.
Ví Dụ 5: BÀI TOÁN TÌM XÂU CON CHUNG DÀI NHẤT
Bài toán: Cho 2 Xâu A và B. Hãy tìm xâu con chung C có độ dài lớn nhất và là xâu
con của A và B
Xâu con chung được định nghĩa như sau: Nếu xóa đi một số kí tự của hai xâu thì hai
xâu con còn lại của chúng bằng nhau.
Ví dụ:
a =(CEACEEC)

b =( AECECA)

Kết quả dãy con chung dài nhất là
c = (ECEC) Hoặc c= (AEEA).
Ý tưởng giải bài toán
Có thể giải bài toán này theo nhiều cách. Nhưng bài toán này có thể sử dụng
phương pháp Quy Hoạch Động với hiệu quả tốt hơn:
- Giả sử: ta có dãy a có độ dài n, dãy b có độ dài m
- Giả sử: L(i,j) là độ dài lớn nhất của dãy con chung của 2 dãy:
12


SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
a1…an

b1…bn

(với i<=n,j<=m)

Ta thử đi tìm công thức đệ qui để tính L(i,j)
Trường hợp đơn giản nhất. Nếu i=0 hoặc j=0 thì L(I,j) = 0,
+ Nếu (i=0) or (j=0) thì L(i,j)=0;
+ Nếu (i>0) and (j >0) and ai=bj ta có L(i,j) = 1 + L(i-1, j-1)
Phương pháp: Dùng bảng để lưu kết quả của các bài toán con mỗi lần cần đến ta
chỉ truy xuất trong bảng.Nếu ta viết một hàm tính độ dài theo hàm như sau:
Function L(I,j: longint):longint;
Begin
If (i=0) or (j=0) then L:=0
Else

if a[i]=b[j] then L:=1 + L(i-1, j-1)

Else L:= max(L(i-1,j),L(i,j-1));
End;
Tuy đoạn chương trình trên vẫn cho kết quả đúng nhưng về thời gian vẫn bị chậm
lại rất nhiều lại rất nhiều do tính lại nhiều lần kết quả bài toán con nào đó và đồng
thời làm cho chương trình dể bị tràn stack. Để khắc phục hạn chế đó ta dung mảng
để lưu lại kết quả các bài toán con. Xuất phát từ trường hợp đơn giản nhất có thể
tìm nghiệm. Kết hợp các nghiệm đã có ta sẽ nhận được nghiệm của bài toán cở lớn
hơn. Tiếp tục như thế cho tới khi tìm ra nghiệm của bài toán.
Ta chỉ cần duyệt qua một lần như sau để lập bảng.
For i:=1 to length(a) do
For j:=1 to length(b) do
If a[i] = b[j] then
L[i,j] := 1+ L[i-1,j-1]

Else

L[i,j]:=max(L[i-1,j],L[i,j-1]);

Khi đó L[n,m] (hay L[length(a),Length(b)]) sẽ cho kết quả là độ dài của xâu con
chung dài nhất.
Để tìm xâu kết quả c: Ta đi ngược từ ô L[n,m] hướng về ô L[0,0] và ta xét
- Nếu ai = bj thì ta đặt ai (Hoặc bj) vào bên trái dãy c(ở đầu xâu)
- Nếu ai ≠ bj thì ta tiến về ô L(i-1,j] trong trường hợp L[i-1,j] > L[i,j-1] (ngược lại
tức là
L[i-1,j] ≤ L[i,j-1] ta tiến về ô L[i,j-1].
Với ví dụ a=(CEACEEC) và b=(AECECA) ta có bảng như sau.
13


SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
j

i

0

1

2

3

4


5

6

0

0

0

0

0

0

0

0

1

0

0

0

1


1

1

1

2

0

0

1

1

2

2

2

3

0

1

1


1

2

2

3

4

0

1

1

2

2

3

3

5

0

1


2

2

3

3

3

6

0

1

2

2

3

3

3

7

0


1

2

3

3

4

4

Xét theo bảng trên thì mỗi lần đi theo thì ta đã chọn được các ô khi a i = bj ( các ô đậm)
khi đó ta được kết quả: c= (AEEC).
Chương trình minh họa
program xauconchung;
uses crt;
var L:array[0..1000,0..1000] of int64;
s1,s2,s3:ansistring;
f:text;
m,n,i,j:longint;
function max(var a,b:longint):longint;
begin
if a>b then max:=a else max:=b;
end;
begin
clrscr;
assign(f, 'Xau.inp'); reset(f);
readln(f,s1);

readln(f,s2);
close(f);
fillchar(l,sizeo(l),0);
m:=length(s1); n:= length(s2);
for i:=1 to m do
for j:=1 to n do
if s1[i]= s2[j] then
l[i,j] : = 1 + l[i-1,j-1]
else l[i,j]:= max(l[i,j-1],l[i-1,j]);
14


SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
s3[0]:=chr(l[m,n]);
i:= m; j:=n;
repeat
if s1[i] = s2[j] then
begin
insert(s1[i],s3,1);
dec(i);
dec(j);
end
else begin
if l[i,j] = L[i-1,j] then dec(i)
else dec(j);
end;
until (i=0) or (j=0);
writeln( s3);
write(l[m,n]);

end.
Qua thực hiện chương trình cho ta thấy dung quy hoạch động đã khắc phục được
nhiều khuyết điểm về mặt thời gian
Ví dụ 6: Bài toán Dãy con chung dài nhất
- Cho hai số nguyên dương M,N (0B1,..,BN. Tìm một dãy dài nhất C là dãy con chung dài nhất của 2 dãy A và B,
Nhận được từ A bằng cách xóa đi một số số hạng và cũng nhận được từ B bằng
cách xóa đi một số số hạng.
Ý tưởng bài toán:
Ta sử dụng mảng 2 chiều L[0..M,0..N], với L[i,j] là độ dài của dãy chung dài nhất của
hai dãy A và B.
Khi đó ta có L[0,j]=0 với j=1...N, L[i,0]=0 với i=1..M.
Xét Nếu 0Trong đó Nếu A[i]=B[j] thì x=1
Nếu A[i] ≠ B[j] thì x=0
Ví dụ 7: Chia kẹo
Có N học sinh giỏi xếp thành 1 hàng dọc, học sinh nào có thành tích cao được đứng
trước học sinh có thành tích thấp hơn. Có M cái kẹo để chia cho N học sinh nói trên
theo nguyên tắc sau:
- Mỗi học sinh được ít nhất 1 cái kẹo và không để thừa lại cái kẹo naofkhoong
chia.

15


SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
- Mỗi học sinh (Trừ học sinh cuối cùng) có số kẹo không ít hơn số kẹo của bạn
đứng ngay sau mình.
Hãy tính xem có bao nhiêu cách chia kẹo.

Input: Dữ liệu vào cho trong File Chiakẹo.inp bao gồm 1 dòng duy nhất có 2 số tự
nhiên N và M cách nhau bởi các dấu cách với 0< N ≤ M ≤ 100.
Output: Kết quả đưa ra File văn bản ChiaKeo.out gồm một số duy nhất là số cách chia
tìm được.
Ý tưởng Thuật toán:
Ta gọi F(i,L,k) là số cách chia L chiếc keojncho i học sinh, trong đó học sinh cuối cùng
(học sinh thứ i) được k chiếc kẹo.
- Số cách chia cần tìm là f(N,L,1)+F(N,L,2)+…+F(N,L,k)+… Ta chỉ cần cho K
chạy đến TRUNC(L/N)
- Với i=1 ta có:
- F[1,L,L]=1,F[1,L,k]=0 với kTa tính mảng F theo với i=1,2,..,N-1; L=i+1,i+2,..,M; k=1…TRUNC(L/(i+1)) theo
công thức.
F[i+1,L,K]=f[i,l-k,k]+f[i,l-k,k+1]+…+f[i,L-k,TRUNC((L-K)/i)]
- Với thứ tự tính toán như trên ta chỉ cần tính 2 mảng f1,f2 hai chiều hoán đổi cho nhau
để tiết kiệm không gian nhớ (bỏ qua chỉ số thứ nhất)
IV/ KIỂM NGHIỆM
Sau khi tôi đưa ra 1 số chương trình có sử dụng phương pháp quy hoạch động nhằm
bồi dưỡng học sinh giỏi tôi nhận thấy học sinh hiểu rõ hơn về vai trò của quy
hoạch động ( công thức truy hồi) học sinh cũng nhanh nắm bắt hơn.
Học sinh đã độc lập hơn trong việc viết chương trình và không bị rập khuôn
trong những trường hợp cụ thể, từ đó khả năng tư duy lập trình tăng lên rõ rệt, các
em biết vận dụng và chọn thuật toán hợp lí cho từng bài toán.
Trong năm học 2015 – 2016 tôi có áp dụng 1 số phương pháp trên trong việc dạy
đội tuyển và kết quả đã có 1 học sinh đạt giải 3 và 1 học sinh được khuyên kích.
C. KẾT LUẬN VÀ ĐỀ XUẤT
I/ KẾT LUẬN
Quy hoạch động có rất nhiều ưu điểm nhưng cũng có nhược điểm, Quy hoạch
động là một việc làm khó và phức tạp. Thông qua 1 số thuật toán khi áp dụng QHĐ
- Học sinh đã được rèn luyện thêm kĩ năng lập trình và thành thạo hơn trong việc

giải quyết các bài toán khó;
Trong quá trình thực hành và làm bài tập cũng tạo cho học sinh tinh thần trách
nhiệm, nhận thức đúng đắn về môn học, khơi dậy lòng say mê môn học và tạo hứng thú
học tập cho học sinh.
16


SKKN:Sử dụng phương pháp quy hoạch động để giải một số bài toán nhằm bồi
dưỡng học sinh giỏi tin học 11.
- Mối quan hệ qua lại giữa các cách giải 1 bài toán sẽ làm học sinh linh hoạt hơn
trong việc lựa trọn thuật toán từ đó có thể lựa chọn thuật toán phù hợp để viết chương
trình
Thông qua các tiết bài tập và thực hành cũng giúp cho giáo viên nắm bắt được
những nhược điểm của học sinh hay mắc phải, những phần kiến thức học sinh thường
nhầm lẫn để củng cố, sửa đổi, bổ sung kịp thời cho các em giúp các em hiểu rõ từng vấn
đề đang vướng mắc trong quá trình thực hiện và học tập.
II/ Ý KIẾN ĐỀ XUẤT.
Để nâng cao chất lượng dạy – học môn tin học, và tạo hứng thú cho các em có
niềm đam mê tin học ngay từ khi đang còn ngồi trên ghế nhà trường rất mong của nhà
trường cùng các ngành có liên quan giúp đỡ về cơ sở vật chất.
Số lượng sách tham khảo môn tin trong nhà trường còn rất hạn chế. Kính mong
được nhà trường và thư viện quan tâm tạo điều kiện bổ sung thêm tài liệu cho học sinh
và giáo viên có điều kiện tiếp cận thêm với tri thức mới.
Trên đây là một số ví dụ tôi đã sử dụng phương pháp QHĐ vào dạy học bồi
dưỡng học sinh giỏi môn tin học 11. Tuy nhiên còn nhiều mặt hạn chế. Rất mong được
sự đóng góp ý kiến của đồng nghiệp để SKKN của tôi có hiệu quả hơn. Đồng thời tôi
mong rằng với chút ít kinh nghiệm của mình có thể góp phần nâng cao chất lượng bộ
môn. Tôi xin chân thành cảm ơn!
XÁC NHẬN CỦA THỦ TRƯỞNG Tĩnh gia, ngày 19 tháng 05 năm 2016
ĐƠN VỊ

Tôi xin cam đoan đây là SKKN của
mình viết, không sao chép nội dung
của người khác.

17