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

Phân loại và vận dụng phương pháp duyệt toàn bộ trong bồi dưỡng học sinh giỏi giúp nâng cao kết quả thi học sinh giỏi cấp tỉnh môn tin học

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 (223.14 KB, 32 trang )

SỞ GIÁO DỤC VÀ ĐÀO TẠO THANH HOÁ

TRƯỜNG THPT TRIỆU SƠN 3

SÁNG KIẾN KINH NGHIỆM

PHÂN LOẠI VÀ VẬN DỤNG PHƯƠNG PHÁP DUYỆT
TOÀN BỘ TRONG BỒI DƯỠNG HỌC SINH GIỎI GIÚP
NÂNG CAO KẾT QUẢ THI HỌC SINH GIỎI CẤP TỈNH
MÔN TIN HỌC

Người thực hiện: Lê Thị Quỳnh
Chức vụ: TPCM
Đơn vị công tác: Trường THPT Triệu Sơn 3
SKKN thuộc môn: Tin học

THANH HOÁ NĂM 2020


MỤC LỤC

1. MỞ ĐẦU...........................................................................................................1
1.1. Lý do chọn đề tài............................................................................................................1
1.2. Mục đích nghiên cứu.....................................................................................................1
1.3. Đối tượng nghiên cứu...................................................................................................1
1.4. Phương pháp nghiên cứu..............................................................................................2
2. NỘI DUNG......................................................................................................3
2.1. Cơ sở lý luận...................................................................................................................3
2.2. Thực trạng của vấn đề cần giải quyết.......................................................................3
2.3. Các giải pháp giải quyết vấn đề.................................................................................3
2.3.1. Phân loại các cách duyệt toàn bộ............................................................................3


2.3.1.1. Duyệt toàn bộ bằng cách sử dụng các vòng lặp lồng nhau..........................3
2.3.1.1.1. Phát biểu bài toán................................................................................................3
2.3.1.1.2. Nhận xét.................................................................................................................4
2.3.1.2. Duyệt toàn bộ bằng cách sử dụng giải thuật quay lui....................................5
2.3.1.2.1. Phát biểu bài toán................................................................................................5
2.3.1.2.2. Nhận xét.................................................................................................................6
2.3.1.3. Duyệt toàn bộ bằng cách sử dụng giải thuật quay lui đặt nhánh cận.........6
2.3.1.3.1. Phát biểu bài toán................................................................................................6
2.3.1.3.2. Nhận xét.................................................................................................................7
2.3.2. Các ví dụ vận dụng....................................................................................................8
2.3.2.1. Duyệt toàn bộ bằng cách sử dụng các vòng lặp lồng nhau..........................8
2.3.2.2. Duyệt toàn bộ bằng cách sử dụng giải thuật quay lui..................................10
2.3.2.3. Duyệt toàn bộ bằng cách sử dụng giải thuật quay lui đặt nhánh cận.......13
2.4. Hiệu quả của sáng kiến kinh nghiệm......................................................................15
3. KẾT LUẬN, KIẾN NGHỊ............................................................................17
3.1. Kết luận..........................................................................................................................17
3.2. Kiến nghị........................................................................................................................17
TÀI LIỆU THAM KHẢO................................................................................18
DANH MỤC.......................................................................................................19
PHỤ LỤC...........................................................................................................20



1. MỞ ĐẦU
1.1. Lý do chọn đề tài
Môn Tin học trong trường THPT có vị trí quan trọng hơn rất nhiều so với
môn Tin học ở các cấp học dưới, vì đó là những kiến thức cơ bản nhất, định
hướng rõ ràng nhất khi các em chập chững bước vào ngưỡng cửa công nghệ
thông tin. Cũng ở cấp học này, các em được thử sức về lập trình thực sự thông
qua kỳ thi học sinh giỏi (HSG) các cấp, từ đó thể hiện được nhiều phẩm chất, kỹ

năng của các em như: tư duy mạch lạc, kiến thức của nhiều môn học được huy
động, nhanh nhạy trong cả suy nghĩ, tư duy lẫn việc gõ bàn phím.
Qua những năm nghiên cứu và giảng dạy thực tế tại các lớp mũi nhọn, và bồi
dưỡng (cũng như đồng phụ trách bồi dưỡng) học sinh ôn luyện thi HSG cấp
Tỉnh, tôi nhận thấy rằng những chuyên đề bồi dưỡng HSG môn Tin học quả thật
là những chuyên đề khó, không chỉ đối với học sinh mà ngay cả với giáo viên
phụ trách.
Trong các đề thi HSG cấp Tỉnh, hoặc đề thi HSG các cấp ở các tỉnh khác
luôn xuất hiện những bài toán có kích thước lớn, đó là những bài toán khó. Để
nghĩ ra được một thuật giải ngay tại thời điểm làm bài là điều không dễ dàng. Có
một phương pháp luôn cho kết quả đúng nhưng lại hạn chế là chậm về mặt thời
gian, một phương pháp mà có thể trở thành phương pháp tình thế để học sinh chỉ
có thể ăn được một số test giới hạn, thậm chí nếu vận dụng thêm các kỹ thuật
khác và cài đặt tốt thì có thể ăn được 100% test, đó là phương pháp “duyệt toàn
bộ”. Vì vậy, tôi đã chọn đề tài “Phân loại và vận dụng phương pháp duyệt
toàn bộ trong bồi dưỡng học sinh giỏi giúp nâng cao kết quả thi học sinh giỏi
cấp Tỉnh môn Tin học” làm sáng kiến kinh nghiệm của mình trong năm học
2019 – 2020 để trao đổi với đồng nghiệp. Đây là một phương pháp tôi đã thực
hiện rất hiệu quả tại ngôi trường THPT Triệu Sơn 3, đồng thời cũng hy vọng
cách làm này sẽ được hoàn thiện, bổ sung và nhân rộng trong các trường THPT
khác trong Tỉnh.
1.2. Mục đích nghiên cứu
- Tổng hợp, phân loại các dạng của bài toán duyệt toàn bộ
- Đánh giá trình độ nhận thức của học sinh so với mục tiêu dạy học nhằm điều
chỉnh hoạt động dạy và hoạt động học.
1.3. Đối tượng nghiên cứu
- Thuật toán sử dụng các vòng lặp lồng nhau.
- Thuật toán quay lui.
- Thuật toán đặt nhánh cận.
- Một số bài toán thi HSG các cấp.

1


- Sự tư duy, ý thức học tập của học sinh ôn thi học sinh giỏi.
1.4. Phương pháp nghiên cứu
Để thực hiện đề tài này, tôi đã sử dụng các phương pháp:
- Phương pháp nghiên cứu xây dựng cơ sở lí thuyết: Cơ sở lý thuyết là phương
pháp duyệt bằng cách sử dụng các vòng lặp lồng nhau, phương pháp quay lui,
phương pháp đặt nhánh cận; một số bài toán trong các đề thi các cấp; Sự hứng
thú trong giờ học môn Tin học và ý thức tự học của học sinh đối với môn học.
- Phương pháp điều tra khảo sát thực tế, thu thập thông tin: Thông qua kết quả
điều tra mức độ hiểu về thuật toán sử dụng các vòng lặp lồng nhau, thuật toán
quay lui, đặt nhánh cận của học sinh khá giỏi lớp 11 trường THPT Triệu Sơn 3.
- Phương pháp thống kê, xử lý số liệu: Trên cơ sở các kết quả đạt được, thống
kê các số liệu, xử lí số liệu để so sánh giữa nhóm thực nghiệm và đối chứng.

2


2. NỘI DUNG
2.1. Cơ sở lý luận
Duyệt toàn bộ là phương pháp liệt kê tất cả các phần tử của một tập hợp D
hữu hạn nào đó, từ đó hoặc là chỉ ra một phần tử thỏa mãn một tiêu chí tối ưu
hoặc là đếm số lượng các phần tử thỏa mãn điều kiện cho trước. Cách tư duy
này xuất phát từ tập D là hữu hạn và tận dụng tốc độ tính toán nhanh của máy
tính (mà tốc độ này luôn tăng trưởng theo cấp số nhân). Có thể nói đây là cách
tư duy đơn giản rất dễ viết chương trình. Tuy nhiên, có thể thấy rằng phương
pháp này có hạn chế khi số lượng các phần tử của tập hợp D lớn. Nó thể hiện ở
chỗ thời gian tính toán để cho ra kết quả thường không chấp nhận được, ngay cả
trong trường hợp các máy tính đủ mạnh.

Do đó phương pháp duyệt toàn bộ, ngoài việc tổ chức liệt kê các phần tử
sao cho đảm bảo duyệt qua hết các phần tử, cần phải vận dụng kết hợp các
phương pháp cho phép bỏ qua hoặc gộp một số phần tử, điều này cải thiện rất
đáng kể thời gian thực hiện của chương trình, thậm chí trong nhiều trường hợp
chúng ta thu được các chương trình rất hiệu quả.
2.2. Thực trạng của vấn đề cần giải quyết
Duyệt toàn bộ là phương pháp mà hầu hết học sinh ôn thi HSG đều nắm
được, đều hiểu rất rõ nguyên lý hoạt động. Tuy nhiên, đa số học sinh mới chỉ
nghĩ đến duyệt toàn bộ bằng cách sử dụng các vòng lặp lồng nhau hoặc duyệt
quay lui đối với những bài toán mức độ khá đơn giản. Việc duyệt sử dụng nhánh
cận (duyệt quay lui đặt nhánh cận) thực sự là thử thách, là khó khăn đối với cả
giáo viên và học sinh. Vì vậy, trong phạm vi đề tài này, tôi mạnh dạn đề xuất
một vài cách phân loại và vận dụng, đó là kinh nghiệm của bản thân đã áp dụng
vào việc bồi dưỡng học sinh ôn thi HSG cấp Tỉnh.
2.3. Các giải pháp giải quyết vấn đề
2.3.1. Phân loại các cách duyệt toàn bộ
Trong phạm vi đề tài này, tôi xin đưa ra ý kiến phân loại sau khi đã nghiên
cứu tham khảo từ nhiều kênh khác nhau, áp dụng và kiểm nghiệm thực tế qua
quá trình bồi dưỡng cho học sinh thi HSG cấp Tỉnh trong những năm học gần
đây.
2.3.1.1. Duyệt toàn bộ bằng cách sử dụng các vòng lặp lồng nhau
2.3.1.1.1. Phát biểu bài toán
Nhóm bài toán sử dụng phương pháp duyệt toàn bộ đầu tiên là nhóm các
bài toán liệt kê bằng cách sử dụng các vòng lặp lồng nhau. Bài toán cơ bản
thuộc loại này có thể phát biểu như sau:

3


Cho k là một hằng số (không phụ thuộc vào dữ liệu). Hãy liệt kê tất cả

các bộ (x1, x2,…,xk) xi  Di. ở đây Di là một tập hợp hữu hạn các phần tử nào
đó.
Để liệt kê các dãy này thông thường chúng ta sẽ sử dụng k vòng lặp lồng
nhau dạng:
For x1  D1 do
For x2 D2 do
..........
For xk  Dk do...
Nếu như lực lượng mỗi tập Di là O(n) thì thời gian thực hiện việc liệt kê
toàn bộ theo cách trên là Nk. Đây là con số khá lớn nếu như n, k lớn. Chính vì
vậy cần phải có các kĩ thuật cải tiến để giảm thời gian thực hiện. Không có một
nguyên tắc chung nào để làm điều này cả.
Ví dụ: cho 2 dãy số nguyên a1, a2, ....an và b1, b2, ... bm . Hãy tìm giá trị nhỏ nhất
của

ai  b j với 1 i n , 1  j m .
Phương pháp để giải quyết bài toán này là duyệt toàn bộ các cặp (i, j) (có

thể thấy có n x m cặp như vậy) để tìm ra cặp có ai  b j nhỏ nhất.
For i:=1 to n do
For j:=1 to m do
If abs(a[i]+b[j])< min then min := abs(a[i]+b[j]);
Thuật toán có độ phức tạp O(mn) và với m, n lớn (cỡ khoảng 100000) thì
cách duyệt toàn bộ như trên không có hiệu quả. Vì vậy, bài toán này có cải tiến
nhằm tăng thời gian tìm kiếm như sau:
Nhận xét: |Ai + Bj| min khi giá trị này càng gần 0 càng tốt.
Dựa vào nhận xét trên ta giải tiếp như sau:
Bước 1: Sắp xếp 2 dãy tăng dần, độ phức tạp là Max(O(NlogN), O(MlogM))
Bước 2: Độ phức tạp là Max(O(N), O(M))
Xét dãy A từ đầu dãy i = 1 và dãy B từ cuối dãy j = N

Min := |A1 + Bn|
Lặp khi i <= N và 1 <= j
- Nếu Ai + Bj = 0 thì min = 0 và thoát
- Nếu Ai + Bj < 0 thì cần phải tăng i, vì nếu giảm j thì Ai + Bj sẽ càng < 0
hơn nữa
- Nếu Ai + Bj > 0 thì cần phải giảm j, vì nếu tăng i thì Ai + Bj sẽ càng > 0
hơn nữa.
Như vậy độ phức tạp của bài toán khi cải tiến là Max(O(NlogN), O(MlogM)).
2.3.1.1.2. Nhận xét
4


Ưu điểm:
- Dễ cài đặt, cài đặt ngắn gọn.
Hạn chế:
- Không tối ưu về mặt thời gian
2.3.1.2. Duyệt toàn bộ bằng cách sử dụng giải thuật quay lui
2.3.1.2.1. Phát biểu bài toán
Thuật toán quay lui dùng để giải bài toán liệt kê các cấu hình. Mỗi cấu
hình được xây dựng bằng cách xây dựng từng phần tử, mỗi phần tử được chon
bằng cách thử tất cả các khả năng. Giả thiết cấu hình cần liệt kê có dạng (x 1,
x2,....xn). khi đó thuật toán quay lui được thực hiện qua các bước sau:
1) Xét tất cả các giá trị x1 có thể nhận, thử cho x1 nhận lần lượt các giá trị đó.
Với mỗi giá trị thử gán cho x1 ta sẽ:
2) Xét tất cả các giá trị x2 có thể nhận lại thử cho x2 nhận lần lượt các giá trị đó.
Với mỗi giá trị thử gán cho x2 lại xét tiếp các khả năng chọn x3....
.........
n) xét tất cả các giá trị xn có thể nhận, thử cho xn nhận lần lượt các giá trị đó,
thông báo cấu hình tìm được (x1,x2,....xn).
Trên phương diện quy nạp, có thể nói rằng thuật toán quay lui liệt kê các

cấu hình n phần tử dạng (x1, x2,...xn) bằng cách thử cho x1 nhận lần lượt các giá
trị có thể. Với mỗi giá trị thử gán cho x 1 lại liệt kê tiếp cấu hình n-1 phần tử (x 2,
x3,.....xn).
Mô tả của thuật toán quay lui có thể mô tả như sau:
{Thủ tục này thử cho xi nhận tất cả các giá trị mà nó có thể nhận}
 Mô hình 1:
Procedure Try(i: integer);
Begin
For (mọi giá trị V có thể gán cho x1) do
Begin
<Thử cho xi:= V>;
<ghi nhận việc cho x1 nhận giá trị V( nếu cần)>;
If (xi là phần tử cuối cùng trong cấu hình) then
<Thông báo cấu hình tìm được>
Else Try(i+1); { gọi đệ quy để chon tiếp xi+1}
khác>;
End;
End;

 Mô hình 2:
Procedure Try(i: integer);
5


Begin
if (xi là vị trí cuối cùng trong cấu hình) then
<Thông báo cấu hình tìm được>
else
For ( mọi giá trị V có thể gán cho x1) do

Begin
<Thử cho xi:= V>;
<ghi nhận việc cho x1 nhận giá trị V( nếu cần)>;
Try(i+1); { gọi đệ quy để chon tiếp xi+1}
khác>;
End;
End;

Thuật toán quay lui sẽ bắt đầu bằng lời gọi Try(1).
Ví dụ: Sinh toàn bộ xâu nhị phân có độ dài N cho trước.
Phương pháp quay lui được áp dụng trong thủ tục sau:
Procedure Try(k:integer); {sinh xâu nhị phân có độ dài k}
Var i:integer;
Begin
For i:=0 to 1 do {xét mọi khả năng của x[k]}
Begin
x[k] := i;
if k = N then print {Nếu sinh được xâu nhị phân độ
dài N thì hiện kết quả}
else try(k+1); {gọi đệ qui để sinh tiếp x[k+1]}
End;
End;

2.3.1.2.2. Nhận xét
Ưu điểm:
- Dễ cài đặt, cài đặt ngắn gọn.
Hạn chế:
- Không tối ưu về mặt thời gian
2.3.1.3. Duyệt toàn bộ bằng cách sử dụng giải thuật quay lui đặt nhánh cận

2.3.1.3.1. Phát biểu bài toán
Có một số bài toán tìm nghiệm tối ưu, nếu sử dụng phương pháp quay lui
thì sẽ tìm hết mọi phương án của nghiệm sau đó chọn lấy một nghiệm tối ưu
nhất đáp ứng yêu cầu của bài toán. Như vậy không gian tìm kiếm là vét cạn toàn
bộ khả năng xảy ra của nghiệm, điều này làm cho chương trình không tối ưu về
mặt thời gian.
Phương pháp nhánh cận là một cải tiến của phương pháp quay lui, được
áp dụng để tìm nghiệm tối ưu của bài toán. Đây là phương pháp rất khó, các bài
6


toán áp dụng phương pháp này thường là các bài toán ở mức độ câu cuối (nếu
có) trong các đề thi HSG cấp Tỉnh hoặc trong đề thi ở phạm vi lớn hơn cấp Tỉnh.
Nó cũng thực sự là thử thách đối với cả giáo viên và học sinh.
Tư tưởng của phương pháp nhánh cận như sau: Giả sử đã xây dựng được
k thành phần (x1, x2, ..., xk) của nghiệm và khi mở rộng thêm (x 1, x2, ..., xk, xk+1),
nếu biết rằng tất các các nghiệm mở rộng của nó (x 1, x2, ..., xk+1, ...) đều không
tốt bằng nghiệm cũ thì ta không cần mở rộng thêm nữa. Như vậy, với phương
pháp nhánh cận, ta không cần phải duyệt toàn bộ các phương án để tìm nghiệm
tốt nhất mà bằng cách đánh giá thành phần mở rộng, ta có thể cắt bỏ những
phương án không cần thiết, do đó việc tìm nghiệm tối ưu sẽ nhanh hơn. Cái khó
của việc áp dụng phương pháp nhánh cận là đánh giá được thành phần mở rộng,
nếu đánh giá được tốt sẽ giúp bỏ được nhiều phương án không cần thiết, khi đó
thuật toán nhánh cận sẽ cho hiệu quả tốt về mặt thời gian.
Có thể tổng quan phương pháp này bằng mô hình sau:
Procedure init;
Begin
<khởi tạo một cấu hình bất kì BESTCONFIG>;
End;
{ thủ tục này thử chon cho x 1 tất cả các giá trị nó có thể

nhận}
Procedure try(i:integer);
Begin
{đánh giá thành phần mở rộng}
If BESTCONFIG > then exit;
For (mọi giá trị V có thể gán cho x1) do
Begin
<thử cho x1:=V>;
If <tìm thấy nghiệm> then <cập nhật BESTCONFIG>
Else try(i+1);
<bỏ ghi nhận việc thử cho x1=V(nếu cần)>;
End;
End;
Begin
Init;
Try(1);
<thông báo cấu hình tối ưu BESTCONFIG>
End.

2.3.1.3.2. Nhận xét

7


Ưu điểm:
- Tối ưu về mặt thời gian
Hạn chế:
- Khó đánh giá được thành phần mở rộng để loại bỏ những nghiệm không
tối ưu.

2.3.2. Các ví dụ vận dụng.
Các bài toán vận dụng trong phần này chủ yếu hướng đến tính tiêu biểu
cho mỗi dạng được phân loại. Có thể sẽ có những bài toán có cách làm khác tối
ưu hơn, nhưng theo phương pháp duyệt toàn bộ là có thể thực hiện được. Mỗi
bài toán nêu ra sẽ có ý tưởng hướng dẫn giải, code bài bằng ngôn ngữ Pascal sẽ
có trong phần phụ lục (do giới hạn về số lượng trang của sáng kiến nghiệm).
2.3.2.1. Duyệt toàn bộ bằng cách sử dụng các vòng lặp lồng nhau
Bài toán 1: Đếm xâu con (Nguồn: Câu 3- Đề thi học sinh giỏi Tỉnh Thanh
Hóa năm học 2018 - 2019)
Cho xâu S bao gồm các chữ cái ‘A’..’Z’ và các chữ số ‘0’..’9’.
Yêu cầu: Đếm số xâu con trong xâu S có số lượng chữ cái nhiều hơn số lượng
chữ số (xâu con của xâu S là một dãy kí tự liên tiếp trong xâu S).
Dữ liệu vào: Đọc từ tệp SUBSTR.INP gồm xâu S có độ dài ≤104
Dữ liệu ra: Ghi ra tệp SUBSTR.OUT kết quả tìm được.
Ví dụ:
SUBSTR.INP
AC54C

SUBSTR.OUT
6

 Hướng dẫn giải:
- Gọi a[i] là mảng các phần tử chữ cái
b[i] là mảng các phần tử chữ số
Thực hiện 2 vòng lặp lồng nhau để xét toàn bộ các dãy con (liên tiếp) thỏa
mãn điều kiện là số lượng chữ cái trong xâu nhiều hơn số lượng chữ số
For i:=1 to length(s) do
For j:= i to length(s) do
If a[j]-a[i-1]>b[j]-b[i-1] then inc(dem)


- Tìm a[i] và b[i] bằng cách duyệt từ đầu đến cuối xâu
If s[i] in [’0’..’9’] then inc(dems)
a[i]:=demc ; b[i]:=dems

else inc(demc)

(Code tham khảo trong phần phụ lục)
Bài toán 2: (Nguồn: Đề thi đề nghị “Olympic đồng bằng duyên hải Bắc bộ
lớp 10” năm học 2010-2011)
Cho dãy N số nguyên a1, a2, ..., aN và số nguyên dương K.

8


Yêu cầu: Tìm đoạn con liên tiếp không ít hơn K số nguyên trong dãy, sao cho
tổng các số nguyên thuộc đoạn là lớn nhất.
Dữ liệu: Cho trong tệp SUBSEQ.INP, gồm có:
- Dòng đầu chứa hai số nguyên N và K, trong đó N là số lượng các số nguyên
trong dãy và K là số lượng tối thiểu các số nguyên liên tiếp của một đoạn con.
- N dòng tiếp theo, dòng i +1 chứa một số nguyên ai.
Kết quả: Ghi ra tệp SUBSEQ.OUT một số nguyên P, cho biết tổng các giá trị
đoạn con tìm được theo yêu cầu.
Hạn chế:
- 1 ≤ N ≤ 106 và 1 ≤ K ≤ N.
- 50% số test với N ≤ 5 000.
Ví dụ:

SUBSEQ.INP
8 3


SUBSEQ.OUT
120

-20
90
-30
-20
80
-70
-60
125
 Hướng dẫn giải:
*) Cách 1: Có thể dùng phương pháp “duyệt toàn bộ” như sau:
Gọi S[i] = a[1] + a[2] + ... + a[i].
Thực hiện hai vòng lặp lồng nhau để xét toàn bộ tổng của đoạn con không
ít hơn k phần tử:
max := 0;
For i:=1 to N – k + 1 đo
For j:=i + k – 1 to N do
if S[j] – S[i-1] > max then max := S[j] – S[i];

Độ phức tạp của thuật toán là O(N2). Với N lớn thì cách 1 sẽ không đáp
ứng được yêu cầu về mặt thời gian. Như vậy cách này không tối ưu.

9


*) Cách 2: Sử dụng phương pháp qui hoạch động có thể giải quyết bài toán với
độ phức tạp là O(N).
Gọi sumK là tổng của K số.

Gọi Best[i] là tổng lớn nhất của đoạn con có ít nhất k phần tử được kết
thúc tại phần tử thứ i.
Ban đầu:
sumK := a[1] + a[2] + ... + a[k]
Best[k] := sumk;
Việc cập nhật mảng Best được thực hiện như sau:
For i:=k+1 to N do
Begin
sumk := sumk + A[i] – A[i-k]; {tổng k phần tử}
Best[i] := max(Best[i-1]+A[i], sumk);
if result < Best[i] then result := Best[i];
End;

(Code tham khảo trong phần phụ lục)
2.3.2.2. Duyệt toàn bộ bằng cách sử dụng giải thuật quay lui
Bài toán 1: Sinh toàn bộ hoán vị của N số nguyên dương đầu tiên.
Trong bài toán này phương pháp quay lui được kết hợp với kỹ thuật đánh
dấu mảng.
Dùng mảng c[1..n] kiểu logic với ý nghĩa:
 C[i] = true: số nguyên i chưa được sinh ra trước đó, vì vậy mà có thể
đặt x[k] = i.
 C[i] = false: số nguyên i đã được sinh ra trước đó, vì vậy không thể đặt
x[k] = i.
 Ban đầu gán c[i] = true (1 <= i <= N)
Thủ tục sau đây thể hiện phương pháp quay lui:
Procedure Try(k:integer); {sinh xâu nhị phân có độ dài k}
Var i:integer;
Begin
For i:=1 to N do {xét mọi khả năng của x[k]}
If c[i] then {Nếu i chưa được sinh ra trước đó}

Begin
x[k] := i;
c[i] := false; {đánh dấu i đã được sinh ra}
if k = N then print {Nếu sinh được xâu nhị phân độ
dài N thì hiện kết quả}
else try(k+1); {gọi đệ qui để sinh tiếp x[k+1]}
c[i] := true; {bỏ đánh dấu}
End;

10


End;

Bài toán 2: Cái túi
Một tên trộm lọt được vào một gia đình. Hắn mang theo một cái túi có thể
tích M để đựng đồ ăn trộm. Trong nhà có n vật dụng (n ≤ 20), vật thứ i có trọng
lượng là Wi ≤ 100 và giá trị là V i ≤ 100. Vậy tên trộm phải chọn những vật nào
để lấy đi mà tổng giá trị của các vật đó là lớn nhất.
Dữ liệu: file văn bản BAG.INP

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

N dòng tiếp theo mỗi dòng i ghi hai số Wi và Vi cách nhau một dấu cách
Kết quả: file văn bản BAG.OUT

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


Dòng 2: Ghi chỉ số những vật dụng bị lấy đi.


Ví dụ:

BAG.INP
5 11
3 3
4 4
5 4
9 10
4 4
 Hướng dẫn giải:

BAG.OUT
11
1 2 5

Xây dựng x[1..N] là phương án chọn đồ vật:
Với x[i] = 1 tức là chọn đồ vật thứ i
Với x[i] = 0 tức là không chọn đồ vật thứ i.
Như vậy ý tưởng là sinh ra mọi dãy nhị phân độ dài N lưu vào mảng
x[1..N], với mỗi dãy nhị phân như vậy ta thử xem các đồ vật tương ứng ở vị trí
của dãy nhị phân có thể cho vừa vào túi không, nếu có thì hãy tính tổng giá trị
các đồ vật và lựa chọn tổng giá trị tối ưu.
Với test ví dụ của đề bài: ta có thể sinh được 1 dãy nhị phân độ dài 5 là 0
1 1 0 1. Tức là có thể sinh chọn các đồ vật thứ 2, 3 và 5.
Có thể dùng phương pháp quay lui để giải quyết bài toán dễ dàng.
procedure chon_kq;
var
S,W,i:integer;
Begin

S := 0; W := 0;
for i:=1 to N do
Begin
W := W + x[i] * A[i];
S := S + x[i] * C[i];
11


end;
if W <= M then
if S > Smax then
Begin
Smax := S;
kq := x;
end;
end;
procedure try(i:integer);
var
j:integer;
Begin
for j:=0 to 1 do
Begin
x[i] := j;
if i = N then chon_kq
else try(i+1);
end;
end;

(Code tham khảo trong phần phụ lục)
Bài toán 3: Bảng Quảng Cáo

Trên quảng trường trung tâm thủ đô Rome có một bảng quảng cáo hình
chữ nhật gồm N x M ô vuông. Mỗi ô có một bóng đèn, mỗi bóng đèn có 2 trạng
thái tắt hoặc sáng, ứng với mỗi dòng cũng như mỗi cột có một công tắc. Khi tác
động đến một công tắc nào đó tất cả các bóng đèn trên dòng hoặc cột tương ứng
sẽ đổi sang trạng thái ngược lại (đang sáng thành tắt, đang tắt được bật sáng). Để
mừng đội nhà thắng trận trong trận cầu chiều qua người phụ trách bảng quảng
cáo muốn bảng có được nhiều bóng sáng nhất. Với trạng thái bảng quảng cáo
hiện thời cho trước, người phụ trách nhờ bạn lập trình tìm một phương án tác
động lên các công tắc để nhận được trạng thái bảng quảng cáo mong muốn. Bạn
hãy giúp nhà phụ trách thực hiện điều đó.
Dữ liệu: file văn bản với tên QUANGCAO.INP trong đó:
- Dòng đầu chứa 2 số N và M (1≤ N≤ 10, 1≤ M≤ 100).
- Dòng thứ i trong N dòng tiếp theo chứa M số 0 hoặc 1. Số thứ j cho biết trạng
thái của bóng đèn thứ j trên dòng thứ i của bảng (1 tương đương với bóng đèn
sáng, 0 tương đương với bóng đèn tắt).
Kết quả: file QUANGCAO.OUT trong đó:
- Dòng đầu là số bóng đèn sáng trên bảng bạn tìm được.
- Dòng thứ hai chứa S là số lần bạn tác động lên các công tắc.

12


- S dòng tiếp theo lần lượt ghi ra S công tắc theo trình tự cần bật. Dòng thứ i
trong S dòng này chứa 1 xâu độ dài không quá 4, ký tự đầu là 'D' hoặc 'C' tương
ứng với tác động thứ i là lên dòng hay lên cột. Phần còn lại của xâu là chỉ số của
dòng hay cột tương ứng.
Ví dụ:

QUANGCAO.INP
4

1
0
0
1

4
0
1
1
0

0
1
1
0

1
0
0
1

QUANGCAO.OUT
16
4
C1
C4
D1
D4

Ghi chú:

- Các số trên một dòng được ghi cách nhau bởi ít nhất 1 khoảng trắng.
- Không cần kiểm tra dữ liệu.


Hướng dẫn giải:

- Dùng mảng D[1..100] trong đó D[j] lưu số đèn bật ở cột j
- Vì 1 <= N <= 10, nên sinh mọi trạng thái của một dãy nhị phân gồm N bít.
Với ý nghĩa như sau: Bít thứ i = 1 tức là sẽ bật công tắc tại dòng i và bít thứ i =
0 thì không bật công tắc ở dòng i.
- Với mỗi dãy nhị phân tạo được thì sẽ thử xem ở cột j có cần phải bật công tăc
không? Cột j cần bật công tắc khi mà số đèn bật ít hơn số đèn tắt.
Độ phức tạp của thuật toán là O(2N*M)
(Code tham khảo trong phần phụ lục)
2.3.2.3. Duyệt toàn bộ bằng cách sử dụng giải thuật quay lui đặt nhánh cận
Trong phạm vi đề tài này, tôi chỉ nêu các bài tập nhánh cận ở mức độ đơn
giản, các bài toán liên quan đến nhánh cận “kinh điển” sẽ cần phải mở
rộng kiến thức liên quan đến nhiều phương pháp khác như tìm đường đi
ngắn nhất, cây khung nhỏ nhất,... những nội dung đó vượt quá phạm vi
của đề tài này, vì vậy, tôi xin được dành cho đề tài lớn hơn.
Bài toán 1: Xếp valy
Một valy có thể chứa tối đa W đơn vị trọng lượng. Có N đồ vật, số lượng
mỗi loại không hạn chế. Loại đồ vật thứ i có trọng lượng là Ai và có giá trị là Ci.
Hỏi nên chọn những đồ vật nào và số lượng bao nhiêu để xếp vào valy sao cho:
- Tổng trọng lượng của các đồ vật không vượt quá giới hạn W của valy
- Tổng giá trị của đồ vật là lớn nhất.
Dữ liệu: Đọc từ file VALY.INP
13



- Dòng 1 chứa N và M (1 ≤ N, M ≤ 100)
- N dòng tiếp theo, mỗi dòng chứa hai số A[i] và C[i].
Kết quả: Ghi ra file VALY.OUT
- Dòng đầu là giá trị lớn nhất
- Các dòng tiếp theo mỗi dòng ghi hai số là số hiệu của đồ vật được chọn và số
lượng của vật đó.

Ví dụ:

4
50
19
80
21

VALY.INP
100
50
20
90
25

VALY.OUT
110
2 1
3 1



Hướng dẫn giải:

Với mỗi loại đồ vật i, gọi Ti là giá trị riêng của nó: Ti = Ci / Ai. Sau đó sắp
các loại đồ vật theo thứ tự giảm dần của Ti.
Giả sử đã chọn được một số đồ vật trong i đồ vật đầu tiên. Điều kiện để
chọn k vật của đồ vật thứ i + 1 là:
S + T[i+1]*(M – W) > Smax
Trong đó:
- S là tổng giá trị của các vật đồ vật đang có trong valy
- W là tổng trọng lượng của các đồ vật đang có trong valy
- smax là tổng giá trị valy của một các xếp đã tìm được nhưng chưa tối ưu. Có thể
khởi tạo smax ban đầu bằng 0.
(Code tham khảo trong phần phụ lục)
Bài toán 2: Xâu ABC (nguồn: thầy Lê Minh Hoàng)
Hãy tạo một xâu chỉ gồm các ký tự A, B, C sao cho:
Có độ dài N cho trước (N <= 100)
Hai đoạn con liên tiếp nhau đều khác nhau
Có ít ký tự C nhất.
Dữ liệu: Đọc từ file ABC.INP một dòng duy nhất chứa số nguyên N
Kết quả: Ghi ra file ABC.OUT là xâu kết quả tìm được.
Ví dụ:

14


ABC.INP

ABC.OUT

7




ABACABA

Hướng dẫn giải:

Ta có nhận xét trong 4 ký tự liên tiếp luôn có ít nhất một ký tự C.
Do đó điều kiện nhánh cận tại bước duyệt ký tự i của xâu là
- Xâu có i ký tự đã tạo được không có 2 đoạn con liên tiếp trùng nhau.
- s(i) + (n-i) div 4 < smin
Trong đó
- s(i) là số ký tự C đã dùng để tạo xâu i ký tự
- smin là số ký tự C của một xâu khác thỏa mãn 2 yêu cầu đầu của đề bài nhưng
chưa tối ưu. Có thể khởi tạo smin ban đầu là một số đủ lớn.
(Code tham khảo trong phần phụ lục)
2.4. Hiệu quả của sáng kiến kinh nghiệm.
Sau ba năm học áp dụng phương pháp này vào ôn luyện thi học sinh giỏi
cấp Tỉnh (năm học 2017-2018 phụ trách chính, năm học 2018-2019 và năm học
2019-2020 đồng phụ trách một vài chuyên đề, trong đó có chuyên đề tìm kiếm
nhị phân và chuyên đề duyệt toàn bộ), tôi nhận thấy các em hứng thú hơn và
hiểu rõ hơn nội dung, bản chất của mỗi thuật toán. Đặc biệt, các em đã nhìn
nhận để giải quyết bài toán bằng phương pháp này rất hiệu quả. Từ đó, mở ra
khả năng hứng thú học tập cho các nội dung (chuyên đề) khác, cách tư duy bài
toán cũng đa dạng và khoa học hơn. Kết quả thi học sinh giỏi cũng tăng lên. Cụ
thể như sau:
* Đối với nhóm học sinh đối chứng:

STT
1
2
3

4

Họ và tên
Hà Minh Dũng
Trịnh Việt Đức
Đỗ Phương Nam
Nguyễn Văn Tuấn

Lớp
11B4
11B4
11C3
11C3

Kết quả thi HSG
Điểm
Xếp giải
10.0
KK
8.5
Không
6.5
Không
9.0
Không

Năm học
2015-2016
2016-2017


15


* Đối với nhóm học sinh thực nghiệm:
STT
1
2
3
4
5
6

Họ và tên

Lớp

Đào Công Cường
Lê Thị Hương
Hà Văn Đức
Đào Huy Hiệu
Nguyễn Thị Châm
Lê Ngọc Linh

11D3
11D3
11E4
11E4
11A35
11A35


Kết quả thi HSG
Điểm
Xếp giải
12.0
KK
15.0
Ba
12.5
KK
16.25
Nhì
Không tổ chức được
do dịch covid 19

Năm học
2017-2018
2018-2019
2019-2020

Như vậy, rõ ràng việc hướng dẫn học sinh giải bài toán bằng phương pháp
chuyên sâu về một chủ đề nào đó, có kết hợp các kỹ thuật khác nhau đã giúp các
em có thể giải quyết triệt để nhiều bài toán ở mức độ vừa và khó, các em có thể
nhìn nhận để giải quyết bài toán đặt ra một cách nhanh và chính xác. Từ đó, kết
quả thi học sinh giỏi cấp Tỉnh cũng ngày càng được nâng cao, hướng đến việc
các em sẽ thuận lợi hơn trong quá trình học tập tiếp theo tại các trường đại học,
cao đẳng với đam mê về lĩnh vực công nghệ thông tin.
Với kết quả có được như trên trong những năm học gần đây, tôi thiết nghĩ
đây là một cách làm thực sự hiệu quả, góp phần vào thành công của công tác ôn
thi học sinh giỏi môn Tin học của nhà trường, định hướng rõ ràng hơn cho học
sinh trong việc vạch ra phương pháp học tập hiệu quả lĩnh vực công nghệ thông

tin tại các trường cao đẳng, đại học sau này.

16


3. KẾT LUẬN, KIẾN NGHỊ
3.1. Kết luận.
Thông qua thực hiện đề tài, tôi nhận thấy duyệt toàn bộ là một phương pháp
cần thiết trong việc dạy học lập trình nói chung và ôn thi học sinh giỏi nói riêng.
Việc áp dụng thuật toán này cũng đã đem lại hiệu quả thực sự trong việc ôn thi
học sinh giỏi tại đơn vị THPT Triệu Sơn 3: Học sinh tự tin hơn, học tập tích cực
hơn, chủ động hơn, khả năng tư duy tốt hơn và có kết quả cao hơn.
Vận dụng phương pháp duyệt toàn bộ để giải các bài toán thi HSG các cấp là
một phần rất nhỏ trong các chuyên đề bồi dưỡng HSG. Tôi hy vọng rằng các bài
toán đã được nêu trong đề tài này sẽ là một kênh gợi mở để tham khảo và phát
triển thành tài liệu bổ ích cho các thầy cô giáo và cho các em học sinh trong việc
nghiên cứu và bồi dưỡng HSG các cấp.
3.2. Kiến nghị.
Đối với giáo viên, phải không ngừng tự học, tự bồi dưỡng, tham khảo các
ý kiến chia sẻ từ đồng nghiệp nhất là về các bài tập, các đề thi học sinh giỏi các
cấp. Từ đó vận dụng vào công tác bồi dưỡng học sinh giỏi đạt hiệu quả cao nhất.
Đối với các cấp lãnh đạo, cần tổ chức hội thảo chuyên đề cho giáo viên bộ
môn Tin học hàng năm để giáo viên có dịp được trao đổi, học hỏi kinh nghiệm,
tìm ra những giải pháp, biện pháp tốt, ý tưởng hay giúp nâng cao chất lượng dạy
học nói chung và ôn thi học sinh giỏi nói riêng.
XÁC NHẬN

Thanh Hóa, ngày 30 tháng 06 năm 2020

CỦA THỦ TRƯỞNG ĐƠ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.
Người viết

LÊ THỊ QUỲNH

17


TÀI LIỆU THAM KHẢO
1. Tin học 10, NXB Giáo Dục, 2006. Tác giả: Hồ Sĩ Đàm, Hồ Cẩm Hà, Trần Đỗ
Hùng, Nguyễn Đức Nghĩa, Nguyễn Thanh Tùng, Ngô Ánh Tuyết.
2. Tin học 11, NXB Giáo Dục, 2007. Tác giả: Hồ Sĩ Đàm, Hồ Cẩm Hà, Trần Đỗ
Hùng, Nguyễn Đức Nghĩa, Nguyễn Thanh Tùng, Ngô Ánh Tuyết.
3.Tài liệu chuyên Tin học quyển 1, NXB Giáo Dục. Tác giả Hồ Sĩ Đàm (chủ
biên), Đỗ Đức Đông, Lê Minh Hoàng, Nguyễn Thanh Tùng.
4. Tài liệu Tập huấn giáo viên 2017 (Tỉnh Thanh Hóa).
5. Website />6. Giải thuật và lập trình. Tác giả: Lê Minh Hoàng
7. Website: vnoi.info
8. Website: vn.spoj.pl

18


DANH MỤC
CÁC ĐỀ TÀI SÁNG KIẾN KINH NGHIỆM ĐÃ ĐƯỢC HỘI ĐỒNG
ĐÁNH GIÁ XẾP LOẠI CẤP PHÒNG GD&ĐT, CẤP SỞ GD&ĐT VÀ CÁC
CẤP CAO HƠN XẾP LOẠI TỪ C TRỞ LÊN
Họ và tên tác giả: Lê Thị Quỳnh

Chức vụ và đơn vị công tác: TPCM, trường THPT Triệu Sơn 3

TT

1.

2.

3.

4.

Tên đề tài SKKN

Kết quả
Cấp đánh
đánh giá
giá xếp loại
xếp loại
(Phòng, Sở,
(A, B,
Tỉnh...)
hoặc C)
Sở GD&ĐT
C

Sử dụng sơ đồ tư duy nhằm
tạo hứng thú và nâng cao chất
lượng cho học sinh khi dạy
tiết 21 – bài tập, Tin học lớp

11.
Một số kinh nghiệm giáo dục Sở GD&ĐT
ý thức sử dụng Internet và kỹ
năng sống nhằm nâng cao
nhận thức và kết quả học tập
cho học sinh thông qua bài 9
và chương IV Tin học 10.
Hướng dẫn giải một số bài
Sở GD&ĐT
tập trong sách bài tập Tin học
11 nhằm nâng cao kết quả
học tập cho học sinh và lựa
chọn, bồi dưỡng học sinh
giỏi.
Giải một số bài toán bằng
Sở GD&ĐT
phương pháp tìm kiếm nhị
phân giúp nâng cao hiệu quả
bồi dưỡng học sinh giỏi

Năm học
đánh giá xếp
loại
2012 - 2013

C

2015 – 2016

C


2017 – 2018

B

2018 – 2019

----------------------------------------------------

19


PHỤ LỤC
Các bài code tham khảo này đã được giáo viên và học sinh trường THPT
Triệu Sơn 3 thực hiện với những bộ Test đảm bảo yêu cầu của đề bài và cho kết
quả tin cậy.
Program substr;
const Fi='substr.inp';
Fo='substr.out';
var F1,F2:text;
S,tg:ansistring;
i,j,dems,demc,n:longint;
a,b:array[0..20000] of longint;
dem:qword;
procedure Nhap;
begin
assign(F1,Fi);reset(F1);
assign(F2,Fo);rewrite(F2);
S:='';
while not eof(F1) do

begin
readln(F1,tg);
S:=S+tg;
end;
while pos(' ',S)<>0 do delete(S,pos(' ',S),1);
S:=upcase(S);
end;
begin
Nhap; dem:=0; dems:=0; demc:=0;
fillchar(a,sizeof(f),0);
fillchar(b,sizeof(e),0);
a[0]:=0;b[0]:=0;n:=length(S);
for i:= 1 to n do
begin
if S[i] in ['0'..'9'] then inc(dems) else inc(demc);
a[i]:=demc;b[i]:=dems;
end;
for i:= 1 to n do
for j:= i to n do
if a[j]-a[i-1]>b[j]-b[i-1] then inc(dem);
write(F2,dem);
close(F1);
close(F2);
end.

---------------------------------------------------20


program subseq;
const

maxn=1000000;
fi='subseq.inp';
fo='subseq.out';
var p : array[1..maxn]of integer;
b, s : array[1..maxn]of longint;
n, k, ans, sum : longint;
f : text;
procedure nhapdl;
var i : longint;
begin
assign(f,fi); reset(f);
readln(f,n,k);
for i := 1 to n do readln(f,p[i]);
close(f);
end;
function max (x, y: longint): longint;
begin
max := x;
if x < y then max := y;
end;
procedure tinh;
var j : longint;
begin
sum := 0;
for j := 1 to k do sum := sum + p[j];
S[K] := sum;
B[K] := sum;
Ans := sum;
for j := K+1 to N do begin
S[j] := S[j-1] + P[j] - P[j-K];

B[j] := Max( B[j-1] + P[j], S[j] );
if (Ans < B[j]) then Ans := B[j];
end;
end;
begin
nhapdl;
tinh;
assign(f, fo); rewrite(f); write(f, ans); close(f);
21


end.

---------------------------------------------------Program bag;
const
fi='BAG.INP';
fo='BAG.OUT';
nmax = 20;
var
A,C,x,kq:array[1..nmax] of integer;
N,M,Smax:integer;
f:text;
procedure doc;
var
i:integer;
Begin
assign(f,fi); reset(f);
readln(f,N,M);
for i:=1 to N do readln(f,A[i],C[i]);
close(f);

end;
procedure chon_kq;
var
S,W,i:integer;
Begin
S := 0; W := 0;
for i:=1 to N do
Begin
W := W + x[i] * A[i];
S := S + x[i] * C[i];
end;
if W <= M then
if S > Smax then
Begin
Smax := S;
kq := x;
end;
end;
procedure try(i:integer);
var
j:integer;
Begin
for j:=0 to 1 do
Begin
x[i] := j;
if i = N then chon_kq
else try(i+1);
end;
end;
22



×