SKKN áp dụng phương pháp QHĐ để giải quyết các bài toán tối ưu trong tin học - Pdf 40

Sáng kiến kinh nghiệm 2014 – Mai Hồng Kiên -THPT chuyên

SỞ GIÁO DỤC VÀ ĐÀO TẠO LÀO CAI
TRƢỜNG THPT CHUYÊN TỈNH LÀO CAI

----------

SÁNG KIẾN KINH NGHIỆM
ỨNG DỤNG PHƢƠNG PHÁP QHĐ VÀO GIẢI QUYẾT MỘT
SỐ BÀI TOÁN TRONG TIN HỌC

HỌ TÊN GIÁO VIÊN: MAI HỒNG KIÊN
Đơn vị: Tổ Toán - tin

Năm học 2013 – 2014
1


Sáng kiến kinh nghiệm 2014 – Mai Hồng Kiên -THPT chuyên

MỤC LỤC
Nội dung
1 . Đặt vấn đề
2. Giải quyết vấn đề
2.1 Cơ sở lý luận
2.2 Thực trạng vấn đề
2.3 Các biện pháp thực hiện giải quyết vấn đề
2.3.1 Áp dụng phương pháp QHĐ
2.3.2 Ví dụ minh họa
2.3.3 Một số bài toán tối ưu giải bằng phương pháp QHĐ
2.4 Hiệu quả của SKNN

theo.
- Trong chương trình Tin học THPT lớp 10 học sinh được giới thiệu các kiến thức đại
cương về tin học, lớp 11 học sinh được giới thiệu về lập trình, lớp 12 học sinh được học
về cơ sở dữ liệu. Trong chương trình Tin học THPT thì chương trình lớp 11 là phần
được cho là khó nhất, học sinh phải làm quen với ngôn ngữ lập trình Pascal và nắm
được một số thuật toán. Chương trình tin học lớp 11 nhằm rèn luyện tư duy về thuật
toán cho học sinh, rèn luyện kĩ năng lập trình, tính kiên trì, tỉ mỉ cẩn thận.
- Tuy nhiên từ thực tiễn giảng dạy học sinh đại trà cũng như học sinh đội tuyển tin học
của trường THPT chuyên Lào Cai tôi thấy rằng, học sinh gặp khó khăn khi chuyển lời
giải các bài toán từ toán sang ngôn ngữ lập trình. Đặc biệt là việc phân tích bài toán,
nhận biết bài toán đó có thể giải quyết bằng phương pháp nào, cỏ lời giải tối ưu hay
không ?
Xuất phát từ cơ sở trên, tôi đã chọn đề tài “Áp dụng phương pháp quy hoạch động để
giải các bài toán tối ưu trong tin học”, giúp các học sinh nắm được phương pháp quy
hoạch động khi giải quyết những bài toán tối ưu trong tin học.

3


Sáng kiến kinh nghiệm 2014 – Mai Hồng Kiên -THPT chuyên

2. Giải quyết vấn đề
2.1 .Cơ sở lí luận
- Nguyên lý tối ƣu của Bellman
Phương pháp quy hoạch động cùng nguyên lý tối ưu được nhà toán học Mỹ
R.Bellman đề xuất vào những năm 50 của thế kỷ 20. Phương pháp này đã được áp dụng
để giải hàng loạt bài toán thực tế trong các quá trình kỹ thuật cộng nghệ, tổ chức sản
xuất, kế hoạch hoá kinh tế…
Trong thực tế, ta thường gặp một số bài toán tối ưu loại sau: Có một đại lượng f
hình thành trong một quá trình gồm nhiều giai đoạn và ta chỉ quan tâm đến kết quả cuối

lượng số hạng của dãy B là nhiều nhất, điều khiển ở giai đoạn i thể hiện việc chọn hay
không chọn Ai vào dãy B.
Giả sử dãy đã cho là 1 8 10 2 4 6 7. Nếu ta chọn lần lượt 1, 8, 10 thì chỉ chọn
được 3 số hạng nhưng nếu bỏ qua 8 và 10 thì ta chọn được 5 số hạng 1, 2, 4, 6, 7.
Khi giải một bài toán bằng cách “chia để trị” chuyển việc giải bài toán kích thước
lớn về việc giải nhiều bài toán cùng kiểu có kích thước nhỏ hơn thì thuật toán này
thường được thể hiện bằng các chương trình con đệ quy. Khi đó, trên thực tế, nhiều kết
quả trung gian phải tính nhiều lần.
Vậy ý tưởng cơ bản của quy hoạch động là : 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. Nói
cách khác phương pháp quy hoạch động đã thể hiện sức mạnh của nguyên lý chia để trị
đến cao độ.
Quy hoạch đ ng là kỹ thuật thiết kế bottom-up (từ dưới lên). Nó được bắt đầu với
những trường hợp con nhỏ nhất (thường là đơn giải nhất và giải được ngay). Bằng
cách tổ hợp các kết quả đã có (không phải tính lại) của các trường hợp con, sẽ đạt đạt
5


Sáng kiến kinh nghiệm 2014 – Mai Hồng Kiên -THPT chuyên

tới kết quả của trường hợp có kích thước lớn dần lên và tổng quát hơn, cho đến khi cuối
cùng đạt tới lời giải của trường hợp tổng quát nhất.
Trong một số trường hợp, khi giải một bài toán A, trước hết ta tìm họ bài toán
A(p) phụ thuộc tham số p (có thể p là một véc tơ) mà A(p0)=A với p0 là trạng thái ban
đầu của bài toán A. Sau đó tìm cách giải họ bài toán A(p) với tham số p bằng cách áp
dụng nguyên lý tối ưu của Bellman. Cuối cùng cho p=p 0 s nhận được kết quả của bài
toán A ban đầu.

Tổ chức dữ liệu sao cho đạt các yêu cầu sau:


Dữ liệu được tính toán dần theo các bước.



Dữ liệu được lưu trữ để giảm lượng tính toán lặp lại.



Kích thước miền nhớ dành cho lưu trữ dữ liệu càng nhỏ càng tốt, kiểu dữ

liệu được chọn phù hợp, nên chọn đơn giản dễ truy cập.
Cụ thể
 Các giá trị của Fk thường được lưu trữ trong một bảng (mảng một chiều hoặc
hai, ba, v.v… chiều).
 Cần lưu ý khởi trị các giá trị ban đầu của bảng cho thích hợp, đó là các kết
quả của các bài toán con có kích cỡ nhỏ nhất của bài toán đang
giải: F1 (t (1))  m ax {G1 (t (1), d (1))  F0 (t (0))}
d (1)

 Dựa vào công thức, phương trình truy toán (*) và các giá trị đã có trong bảng
để tìm dần các giá trị còn lại của bảng.
 Ngoài ra còn cần mảng lưu trữ nghiệm tương ứng với các giá trị tối ưu trong
từng gian đoạn.
 Dựa vào bảng lưu trữ nghiệm và bảng giá trị tối ưu trong từng giai đoạn đã
xây dựng, tìm ra kết quả bài toán.
Bước 3: Làm tốt
Làm tốt thuật toán bằng cách thu gọn hệ thức (*) và giảm kích thước miền nhớ.


Loại 1: Không chứa số m trong phép phân tích, khi đó số cách phân tích loại này
chính là số cách phân tích số v thành tổng các số nguyên dương < m, tức là số cách
phân tích số v thành tổng các số nguyên dương ≤ m - 1 và bằng F[m - 1, v].

-

Loại 2: Có chứa ít nhất một số m trong phép phân tích. Khi đó nếu trong các cách
phân tích loại này ta bỏ đi số m đó thì ta s được các cách phân tích số v - m thành
tổng các số nguyên dương ≤ m (Lưu ý: điều này chỉ đúng khi không tính lặp lại các
8


Sáng kiến kinh nghiệm 2014 – Mai Hồng Kiên -THPT chuyên

hoán vị của một cách). Có nghĩa là về mặt số lượng, số các cách phân tích loại này
bằng F[m, v - m]
Trong trường hợp m > v thì rõ ràng chỉ có các cách phân tích loại 1, còn trong
trường hợp m ≤ v thì s có cả các cách phân tích loại 1 và loại 2. Vì thế:

F[m 1, v]; if m > v
F[m, v]= 
F[m-1,v]+F[m,v-m]; if m  v
Bước 2: Tổ chức dữ liệu và chương trình
Ta có công thức xây dựng F[m, v] từ F[m - 1, v] và F[m, v - m]. Công thức này có
tên gọi là công thức truy hồi đưa việc tính F[m, v] về việc tính các F[m', v'] với dữ liệu
nhỏ hơn. Tất nhiên cuối cùng ta s quan tâm đến F[n, n]: Số các cách phân tích n thành
tổng các số nguyên dương ≤ n.
Ví dụ với n = 5, bảng F s là:
F 0 1 2 3 4 5 V

max = 100;
var
F: array[0..max, 0..max] of Integer;
n, m, v: Integer;
9


Sáng kiến kinh nghiệm 2014 – Mai Hồng Kiên -THPT chuyên

begin
Write('n = '); ReadLn(n);
FillChar(F[0], SizeOf(F[0]), 0);
F[0, 0] := 1;
for m := 1 to n do
for v := 0 to n do
if v < m then F[m, v] := F[m - 1, v]
else F[m, v] := F[m - 1, v] + F[m, v - m];
WriteLn(F[n, n], ' Analyses');
end.
Bước 3: Làm tốt
Cải tiến dùng 2 mảng 1 chiều
Cách làm trên có thể tóm tắt lại như sau: Khởi tạo dòng 0 của bảng, sau đó dùng
dòng 0 tính dòng 1, dùng dòng 1 tính dòng 2 v.v… tới khi tính được hết dòng n. Có thể
nhận thấy rằng khi đã tính xong dòng thứ k thì việc lưu trữ các dòng từ dòng 0 tới dòng
k - 1 là không cần thiết bởi vì việc tính dòng k + 1 chỉ phụ thuộc các giá trị lưu trữ trên
dòng k. Vậy ta có thể dùng hai mảng một chiều: Mảng Current lưu dòng hiện thời đang
xét của bảng và mảng Next lưu dòng kế tiếp, đầu tiên mảng Current được gán các giá trị
tương ứng trên dòng 0. Sau đó dùng mảng Current tính mảng Next, mảng Next sau khi
tính s mang các giá trị tương ứng trên dòng 1. Rồi lại gán mảng Current := Next và
tiếp tục dùng mảng Current tính mảng Next, mảng Next s gồm các giá trị tương ứng

Input: file văn bản BAG.INP
-

Dòng 1: Chứa hai số n, M cách nhau ít nhất một dấu cách

-

n dòng tiếp theo, dòng thứ i chứa hai số nguyên dương W[i], V[i] cách nhau
ít nhất một dấu cách

Output: file văn bản BAG.OUT
-

Dòng 1: Ghi giá trị lớn nhất tên trộm có thể lấy

-

Dòng 2: Ghi chỉ số những gói bị lấy
BAG.INP BAG.OUT
5 11

11

33

521

44
54
9 10

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 F[n, M] = F[n 1, M] thì tức là không chọn gói thứ n, ta truy tiếp F[n - 1, M]. Còn nếu F[n, M] ≠ F[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 F[n - 1, M W[n]]. Cứ tiếp tục cho tới khi truy lên tới hàng 0 của bảng phương án.
program Bag;
const
12


Sáng kiến kinh nghiệm 2014 – Mai Hồng Kiên -THPT chuyên

InputFile = 'BAG.INP';
OutputFile = 'BAG.OUT';
max = 100;
var
W, V: Array[1..max] of Integer;
F: array[0..max, 0..max] of Integer;
n, M: Integer;
procedure Enter;
var
i: Integer;
fi: Text;
begin
Assign(fi, InputFile); Reset(fi);
ReadLn(fi, n, M);
for i := 1 to n do ReadLn(fi, W[i], V[i]);
Close(fi);
end;
procedure Optimize;
var
i, j: Integer;
begin
FillChar(F[0], SizeOf(F[0]), 0);

end;
begin
Enter;
Optimize;
Trace;
end.
Bài toán 2: Chia thưởng
Cần chia hết m phần thưởng cho n học sinh sắp theo thứ tự từ giỏi trở xuống sao
cho mỗi bạn không nhận ít phần thưởng hơn bạn xếp sau mình.
1  m, n  70.
Hãy tính số cách chia.
Thí dụ, với số phần thưởng m = 7, và số học sinh n = 4 s có 11 cách chia 7 phần
thưởng cho 4 học sinh theo yêu cầu của đầu bài. Đó là:
Phƣơng án
1
2
3
4
5
6
7
8
9
10
11

   
7
6
5

1
2

0
0
0
0
0
0
0
0
1
1
1

14


Sáng kiến kinh nghiệm 2014 – Mai Hồng Kiên -THPT chuyên

Bài giải
Lập hệ thức
Gọi Chia(i, j) là số cách chia i phần thưởng cho j học sinh, ta thấy:
- Nếu không có học sinh nào (j = 0) thì không có cách chia nào (Chia = 0).
- Nếu không có phần thưởng nào (i = 0) thì chỉ có một cách chia (Chia(0,j) = 1 -

mỗi học sinh nhận 0 phần thưởng). Ta cũng quy ước Chia(0, 0) = 1.
- Nếu số phần thưởng ít hơn số học sinh (i < j) thì trong mọi phương án chia, từ

học sinh thứ i + 1 trở đi s không được nhận phần thưởng nào:

Chia(i, j)

j: số học sinh
j=0

Chia(i, j) = 0

i = 0 and j  0

Chia(i, j) = 1

i 0 }
if i = 0 then {i = 0; j > 0 }
Chia := 1






0
9
1
1
0
9
9
2
1
0
6
6
1
0
0
5
5
2
1
1
3
3
1
1
0

var cc: array[0..MN,0..MN] of longint;
Ta quy ước cc[i, j] chứa số cách chia i phần thưởng cho j
học sinh.

i-j
...
i

[i-j,j]
...
[i,j-1] [i,j]

Theo phân tích của phương án 1, ta có:
 cc[0, 0] = 1; cc[i, 0] = 0, với i:=1..m.
 cc[i, j] = cc[i, i], nếu i < j
 cc[i, j] = cc[i, j-1]+cc[i-j, j], nếu i  j.
Từ đó ta suy ra quy trình điền trị vào bảng cc như sau:
 Khởi trị
 cc[0,0 ]:= 1;
17


Sáng kiến kinh nghiệm 2014 – Mai Hồng Kiên -THPT chuyên

 với i := 1..m: cc[i,0] := 0;
 Điền bảng: Lần lượt điền theo từng c t j:= 1..n. Tại mỗi c t j ta đặt:
 với i := 0..j-1: cc[i,j] := cc[i,i];
 với i := j..m: cc[i,j] := cc[i,j-1]+cc[i-j,j];
Nhận kết quả: Sau khi điền bảng, giá trị cc[m, n] chính là kết quả cần tìm.
Phƣơng án d ng mảng 2 chiều:

Như đã nói ở trên, chìa khóa trong thuật toán quy hoạch động là việc xây dựng các bài
toán con mà ta gọi là mảng quy hoạch động. Mảng này có thể là 1, 2 hoặc có thể nhiều
chiều tùy thuộc vào lời giải của bài toán phụ thuộc vào các loại tham số nào. Tiếp đến là
cách quy nạp thu gọn bài toán sau mỗi bước, tức là không gian bài toán (kích thước dữ
liệu) nhỏ lại, cho đến khi nào ta hoàn toàn có thể giải được bài toán nhỏ (điểm dừng của
quy nạp). Bản chất của công việc này là ta phải xây dựng được lời giải của bài toán qua
các bài toán con, tức là lập được công thức truy hồi, và dựa vào công thức truy hồi, ta s
biết được cần phải khởi tạo như thế nào.
Trong các phần trên, chúng ta đã khảo sát một số bài toán có thể dùng thuật toán quy
hoạch động để giải quyết một cách hiệu quả. Những vấn đề này đều liên quan đến bài
toán tìm phương án tối ưu để thực hiện một công việc nào đó và chúng có chung một
tính chất là đáp án tốt nhất cho một bài toán con vẫn được duy trì khi bài toán con đó
trở thành một phần trong bài toán lớn hơn.
Thuật toán quy hoạch động thường được áp dụng để giải các bài toán tối ưu, bài toán
đếm, … Vì vậy, nếu giới hạn kích thước dữ liệu của các bài toán tối ưu lớn và việc sử
dụng các thuật toán khác (như duyệt, nhánh cận, ...) có độ phức tạp thời gian lớn thì
chúng ta hãy nghĩ đến thuật toán quy hoạch động.

TÀI LIỆU THAM KHẢO

1.Sách giáo khoa tin học 11
2. Sách giáo viên tin học 11
3. Tài liệu giáo khoa chuyên tin

Hồ Sĩ Đàm
Hồ Sĩ Đàm
Hồ Sĩ Đàm

Chủ biên
Chủ biên


Nhờ tải bản gốc

Tài liệu, ebook tham khảo khác

Music ♫

Copyright: Tài liệu đại học © DMCA.com Protection Status