SKKN Một số bài toán quy hoạch động trong bồi dưỡng học sinh giỏi Tin học 11

SKKN Một số bài toán quy hoạch động trong bồi dưỡng học sinh giỏi Tin học 11

Để giải các bài toán trong Tin học, việc xác định Thuật toán để giải bài toán là công việc đặc biệt quan trọng. Tuy nhiên, đối với học sinh các trường THPT việc thiết kế thuật toán để giải quyết tối ưu bài toán gặp nhiều khó khăn.

Trong các đề thi HSG Tin học cấp Tỉnh, có một số bài toán cần sử dụng những kĩ thuật lập trình nâng cao. Mặc dù, cũng có những cách khác để giải bài toán đó nhưng vì các cuộc thi đều có giới hạn về thời gian, cũng như bộ nhớ của chương trình, nên một thuật toán hiệu quả là cực kỳ cần thiết. Và trong những trường hợp như vậy, quy hoạch động là một lựa chọn tốt. Do vậy, tôi đã chọn đề tài “Một số bài toán quy hoạch động trong bồi dưỡng học sinh giỏi Tin học lớp 11”.

 

doc 15 trang thuychi01 24594
Bạn đang xem tài liệu "SKKN Một số bài toán quy hoạch động trong bồi dưỡng học sinh giỏi Tin học 11", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
SỞ GIÁO DỤC VÀ ĐÀO TẠO THANH HOÁ 
 TRƯỜNG THPT HÀM RỒNG
SÁNG KIẾN KINH NGHIỆM
MỘT SỐ BÀI TOÁN QUY HOẠCH ĐỘNG TRONG 
BỒI DƯỠNG HSG TIN HỌC 11
Người thực hiện: Nguyễn Thị Mai Hương
Chức vụ: Giáo viên
SKKN thuộc lĩnh mực (môn): Tin học
THANH HOÁ NĂM 2019
MỤC LỤC
TÊN ĐỀ TÀI:
MỘT SỐ BÀI TOÁN QUY HOẠCH ĐỘNG TRONG BỒI DƯỠNG 
HSG TIN HỌC 11
1. MỞ ĐẦU
1.1. Lý do chọn đề tài
Để giải các bài toán trong Tin học, việc xác định Thuật toán để giải bài toán là công việc đặc biệt quan trọng. Tuy nhiên, đối với học sinh các trường THPT việc thiết kế thuật toán để giải quyết tối ưu bài toán gặp nhiều khó khăn. 
Trong các đề thi HSG Tin học cấp Tỉnh, có một số bài toán cần sử dụng những kĩ thuật lập trình nâng cao. Mặc dù, cũng có những cách khác để giải bài toán đó nhưng vì các cuộc thi đều có giới hạn về thời gian, cũng như bộ nhớ của chương trình, nên một thuật toán hiệu quả là cực kỳ cần thiết. Và trong những trường hợp như vậy, quy hoạch động là một lựa chọn tốt. Do vậy, tôi đã chọn đề tài “Một số bài toán quy hoạch động trong bồi dưỡng học sinh giỏi Tin học lớp 11”.
1.2. Mục đích nghiên cứu
- Nhằm mục đích đóng góp thêm vào ngân hàng bài tập giúp hỗ trợ cho công tác bồi dưỡng học sinh giỏi môn Tin học được tốt hơn.
1.3. Đối tượng và phạm vi nghiên cứu
- Môn Tin học lớp 11 ở trường THPT;
- Học sinh khối 11 trường THPT Hàm Rồng;
1.4. Phương pháp nghiên cứu
- Phân tích, tổng hợp, khảo sát.
- Đánh giá so sánh kết quả của học sinh;
2. NỘI DUNG SÁNG KIẾN KINH NGHIỆM
2.1. PHƯƠNG PHÁP QUY HOẠCH ĐỘNG
Trong chiến lược chia để trị, người ta phân bài toán cần giải thành các bài toán con. Các bài toán con lại tiếp tục phân thành các bài toán con nhỏ hơn, cứ thế tiếp tục cho tới khi ta nhận được các bài toán con có thể giải được dễ dàng. Tuy nhiên, trong quá trình phân chia như vậy, có thể ta sẽ gặp rất nhiều lần cùng một bài toán con. Tư tưởng cơ bản của phương pháp quy hoạch động là sử dụng một bảng để lưu giữ lời giải các bài toán con đã được giải. Khi giải một bài toán con cần đến nghiệm của bài toán con cỡ nhỏ hơn, ta chỉ cần lấy lời giải ở trong bảng mà không cần phải giải lại. Chính vì thế mà các thuật toán được thiết kế bằng quy hoạch động sẽ rất hiệu quả.
Khi nào thì chúng ta cần đến quy hoạch động? Không có một công thức nào cho các bài toán như vậy. Tuy nhiên, có một số tính chất của bài toán mà ta có thể nghĩ đến quy hoạch động. Dưới đây là hai tính chất nổi bật nhất trong số chúng:
- Bài toán có các bài toán con gối nhau.
- Bài toán có cấu trúc con tối ưu.
Thường thì một bài toán có đủ cả hai tính chất này, chúng ta có thể dùng quy hoạch động được. 
Để giải quyết một bài toán bằng quy hoạch động, chúng ta cần tiến hành những công việc sau:
- Tìm nghiệm của các bài toán con nhỏ nhất;
- Tìm ra công thức (hoặc quy tắc) xây dựng nghiệm của bài toán con thông qua nghiệm của các bài toán con cỡ nhỏ hơn;
- Tạo ra một bảng lưu trữ các nghiệm của bài toán con. Sau đó tính nghiệm của các bài toán con theo công thức đã tìm và lưu vào bảng;
- Từ các bài toán con đã giải để tìm nghiệm của bài toán.
2.2. THỰC TRẠNG TRƯỚC KHI ÁP DỤNG SÁNG KIẾN KINH NGHIỆM
Trong quá trình bồi dưỡng học sinh giỏi Tin học 11 có một số bài tập lập trình nếu chỉ áp dụng những thuật toán cơ bản thì thời gian thực hiện chương trình không đảm bảo. Đây cũng là khó khăn lớn đối với học sinh vì các em chưa được làm quen nhiều với các bài tập thiết kế thuật toán quy hoạch động. Vì vậy việc tập hợp những bài toán quy hoạch động thành một hệ thống bài tập để học sinh tham khảo là rất cần thiết.
2.3. MỘT SỐ BÀI TOÁN ÁP DỤNG
Bài 1: Bội số chung nhỏ nhất
Cho trước số tự nhiên N (1<N<100)
Xét tất cả các phân tích N thành tổng các số tự nhiên: N = a1 + a2 +  + ak (1)
Tìm giá trị lớn nhất của BSCNN (a1,a2, , ak) trên tập các bộ số (a1,a2, , ak) thõa mãn đẳng thức (1).
Dữ liệu vào: từ file văn bản BSCNN.INP là 1 số N
Dữ liệu ra: ghi ra file văn bản BSCNN.OUT, bao gồm 2 dòng, dòng thứ nhất ghi giá trị Max tìm được. Dòng thứ hai ghi n bộ số a1,a2, , ak tương ứng, các số cách nhau bằng dấu cách.
Ví dụ:
BSCNN.INP
BSCNN.OUT
22
420
3 3 4 5 7
a) Phân tích thuật toán:
	Áp dụng thuật toán quy hoạch động:
	Gọi a[i,j] là giá trị lớn nhất của BSCNN khi phân tích i thành tổng của j số tự nhiên.
	B[i,j] là giá trị của số thứ j trong cách phân tích i thành tổng của j số tự nhiên để a[i,j] đạt max.
	Khởi tạo: a[i,1]:=i; b[i,1]:=i (1≤j≤i≤N)
	Với mọi j (2≤j≤N) ta xét các khả năng phân tích i (j≤i≤N) để BSCNN của các cách phân tích đó đạt max.
	Ta có: a[i,j]:=max {BSCNN(a[i-t,j-1],t)} với 1≤t≤i-j+1; b[i,j]:=t;
	Giá trị lớn nhất trong các cách phân tích N bằng Max(a[n,i]) với 1≤j≤N
b) Chương trình tham khảo:
program BSCNN;
const fi='BSCNN.INP';
 fo='BSCNN.OUT';
 maxn=100;
var a: array[1..maxn,1..maxn] of longint;
 b: array[1..maxn,1..maxn] of byte;
 n: integer;
 f: text;
{-------------------------------------------}
procedure init;
begin
assign(f,fi);reset(f);
readln(f,n);
close(f);
end;
{-------------------------------------------}
function bscnn(x,y: longint): longint;
var tg,i,j: longint;
begin
 i:=x;
 j:=y;
 while i mod j0 do
 begin
 tg:= j;
 j:= i mod j;
 i:=tg;
 end;
 bscnn:= (x*y)div j;
end;
{---------------------------------------------}
procedure solution;
var i,j,t: integer;
 tg: longint;
begin
 for i:=1 to n do
 begin
 a[i,1]:=i;b[i,1]:=i;
 end;
 for j:=2 to n-1 do
 for i:=j+1 to n do
 begin
 a[i,j]:=0;
 for t:=1 to i-j+1 do
 begin
 tg:=bscnn(a[i-t,j-1],t);
 if a[i,j]<tg then
 begin
 a[i,j]:=tg;
 b[i,j]:=t;
 end;
 end;
 end;
end;
{---------------------------------------------}
procedure result;
var i,j: integer;
begin
 assign(f,fo);
 rewrite(f);
 j:=n;
 for i:=1 to n-1 do
 if a[n,n]< a[n,i] then
 begin
 a[n,n]:=a[n,i];
 j:=i;
 end;
 writeln(f,a[n,n]);
 i:=n;
 while j>0 do
 begin
 write(f,b[i,j],' ');
 i:=i-b[i,j];
 j:=j-1;
 end;
close(f);
end;
{------------------------------------------}
BEGIN
 init;
 solution;
 result;
END.
Bài 2:	 Dãy con đối xứng dài nhất
Dãy số có A1, A2, , An được gọi là đối xứng nếu các cặp số ở các vị trí i và N-i+1 bằng nhau (với i=1..N). Cho trước một dãy số có N phần tử, mỗi phần tử là số nguyên. Hãy tìm cách loại bỏ một số phần tử trong dãy để dãy thu được tạo thành một dãy đối xứng dài nhất.
Dữ liệu vào: tệp văn bản DAYDX.INP có cấu trúc như sau:
+ Dòng 1 chứa số nguyên N (2≤N≤5000);
+ Dòng thứ 2 ghi N số nguyên là các số hạng trong dãy có giá trị tuyệt đối ≤1000, mỗi số cách nhau một dấu cách.
Dữ liệu ra: tệp văn bản DAYDX.OUT với cấu trúc như sau:
+ Dòng đầu ghi số nguyên M là số các số hạng của dãy đối xứng tìm được;
+ Dòng thứ 2 ghi M số hạng của dãy tìm được, mỗi số cách nhau một dấu cách.
Ví dụ:
DAYDX.INP
DAYDX.OUT
13
1 3 2 3 1 5 2 3 4 1 4 3 2
7
2 3 4 1 4 3 2
a) Phân tích thuật toán:
	Áp dụng thuật toán quy hoạch động:
	Gọi L[i,j] (i=1..N, j=1..N) là độ dài lớn nhất của dãy tìm được khi chọn các phần tử của A từ phần tử thứ i đến j. Ta cần tìm L[1,N]
	*) Công thức quy hoạch động:
	L[i,j]=0 với mọi i>j;
	L[i,j]=1 với i=j;
	Nếu A[i]=A[j] thì L[i,j]=L[i+1,j-1]+2, ngược lại L[i,j]=max(L[i,j-1], L[i+1,j]); 
	Sử dụng mảng hai chiều L[1..N, 1..N] (2≤N≤5000)
	Điền các phần tử của mảng nằm trên đường chéo chính k=-1 đến 1-N với điều kiện: Nếu A[i]=A[j] thì L[i,j]=L[i+1,j-1]+2, ngược lại L[i,j]=max(L[i,j-1], L[i+1,j]);
	Kết quả của bài toán là L[1,N].
	Dựa vào mảng L lần ngược từ giá trị L[1,N] để lấy dãy các phần tử tìm được.
b) Chương trình tham khảo:
const
 fi='DAYDX.INP';
 fo='DAYDX.OUT';
 nmax=5000;
var a:array[1..nmax] of integer;
 check: array[1..nmax] of boolean;
 l:array[1..nmax,1..nmax] of integer;
 n:integer;
{-------------------------------------------------}
procedure inputdata;
var f:text; i:integer;
begin
 assign(f,fi);
 reset(f);
 readln(f,n);
 for i:=1 to n do read(f,a[i]);
 close(f);
 fillchar(check,sizeof(check),false);
 fillchar(l,sizeof(l),0);
 for i:=1 to n do l[i,i]:=1;
end;
{------------------------------------------------}
function max(x,y:integer):integer;
begin
 if x>y then exit(x) else exit(y);
end;
{------------------------------------------------}
procedure qhd;
var i,j,k:integer;
begin
 k:=0;
 repeat
 dec(k);
 for i:=1 to n do
 begin
 j:=i-k;
 if a[i] = a[j] then l[i,j]:=l[i+1,j-1]+2
 else l[i,j]:=max(l[i,j-1],l[i+1,j])
 end;
 until k=1-n;
end;
{--------------------------------------------------------------}
procedure trace;
var i,j:integer;
begin
 i:=1;j:=n;
 repeat
 while l[i,j]=l[i+1,j] do inc(i);
 while l[i,j]=l[i,j-1] do dec(j);
 check[i]:=true; check[j]:=true;
 inc(i);dec(j);
 until i>j
end;
{--------------------------------------------------------------}
procedure outputdata;
var f:text; i,j:integer;
begin
 assign(f,fo);
 rewrite(f);
 writeln(f,l[1,n]);
 for i:=1 to n do
 if check[i] then write(f,a[i],' ');
 close(f);
end;
{--------------------------------------------------------------}
BEGIN
 inputdata;
 qhd;
 trace;
 outputdata;
END.
Bài 3:	 Thả bóng
	Kỉ niệm ngày 26/3, Đoàn trường có tổ chức trò chơi thả bóng. Người chơi đứng lên cao và thả quả bóng xuống một các bảng bậc thang chữ nhật. Bảng này được chia thành n x m hình chữ nhật nhỏ, mỗi hình chữ nhật nhỏ có gắn một bậc thang và trên đó có ghi một số nguyên hoặc đặt một cái đinh làm bằng tấm bìa cứng. Người chơi đứng trên thả quả bóng xuống, quả bóng chỉ được lăn theo quy tắc: từ ô (i,j) chỉ được lăn xuống các ô (i+1,j-1), (i+1,j), (i+1,j+1), nếu đi sai quy tắc thì sẽ bị mất quyền chơi còn nếu đi đúng thì mỗi ô mà quả bóng lăn qua sẽ được cộng vào quỹ điểm của người chơi bằng số nguyên được ghi trên ô, còn nếu lăn vào ô có đinh thì số điểm của người chơi sẽ bị trừ đi một nửa hoặc gần một nửa (phần nguyên của số điểm chia 2). Sau khi hoàn thành trò chơi thì số điểm sẽ được quy ra quà cho người chơi. Để khuyến khích người chơi, ban tổ chức sẽ tặng người chơi một số điểm nào đó.
Yêu cầu: Hãy cho người chơi biết có thể nhận được số điểm ít nhất và nhiều nhất mà họ có thể nhận được.
 Dữ liệu vào: từ file THABONG.INP
- Dòng đầu chứa 2 số nguyên n và m (1 ≤ n,m≤1000) là giá trị của các phần tử của dãy A.
- Dòng thứ hai chứa số nguyên b là số điểm mà ban tổ chức tặng người chơi (b<30000).
- Dòng thứ i trong số n dòng tiếp theo chứa m số nguyên không âm là m số của hàng i; nếu ô ghi số 0 có nghĩa là ô đó có đinh còn ngược lại là các số trên ô. 
Dữ liệu ra: ghi ra file THABONG.OUT 
- Dòng đầu ghi số điểm ít nhất mà người chơi đạt được;
- Dòng hai ghi số điểm nhiều nhất mà người chơi đạt được.
Ví dụ:
THABONG.INP
THABONG.OUT
5 5
100
1 7 5 10 2
6 8 4 1 9
9 6 0 7 14
10 18 3 2 0
5 0 6 11 10
18
148
a) Phân tích thuật toán: sử dụng phương pháp quy hoạch động
	- Tìm giá trị lớn nhất:
	+ Gọi L[i,j] là giá trị lớn nhất từ : ô ở hàng tới ô (i,j)
	+ Khi đó ta có: L[i,j]=max(L[i-1,j-1],L[i-1,j],L[i-1,j+1])+giá trị tại ô (i,j) (i=2, 3, ..., n; j=1,2, ...,m);
	Ban đầu ta đặt: L[1,j]=giá trị tại ô (1,j)+p voiứ j=1,2,...,m
	+ Tìm giá trị max tại ô ở hàng n của bảng L
	- Tìm giá trị nhỏ nhất:
	+ Gọi T[i,j] là giá trị nhỏ nhất từ ô ở hàng 1 tới ô (i,j)
	+ Khi đó ta có: T[i,j]=min(T[i-1,j-1],T[i-1,j],T[i-1,j+1])+giá trị tại ô (i,j) (i=2, 3, ..., n; j=1,2, ..., m); nếu giá tri của ô (i,j)=0 thì T[i,j]=T[i,j]-T[i,j] div 2
	Ban đầu ta đặt: T[1,j]=giá trị tại ô (1,j)+p với j=1,2, ..., m; nếu giá trị của ô (i,j)=0 thì T[i,j]= p div 2
	+ Ta tìm giá trị min tại ô ở hàng n của bảng T. 
b) Chương trình tham khảo:
Program ThaBong;
const
 fi='THABONG.INP';
 fo='THABONG.OUT';
 nmax=1000;
var a:array[1..nmax,1..nmax] of integer;
 L:array[1..nmax,1..nmax] of longint;
 n,m,p:integer;
 Hmax,Hmin:longint;
{-------------------------------------------------}
procedure inputdata;
var f:text; i,j:integer;
begin
 assign(f,fi);
 reset(f);
 readln(f,n,m);
 readln(f,p);
 for i:=1 to n do
 for j:=1 to m do read(f,a[i,j]);
 close(f);
end;
{------------------------------------------------}
function max(a,b,c:integer):integer;
var tg:integer;
begin
 tg:=a;
 if tg<b then tg:=b;
 if tg<c then tg:=c;
 max:=tg;
end;
{------------------------------------------------}
function min(a,b,c:integer):integer;
var tg:integer;
begin
 tg:=a;
 if tg>b then tg:=b;
 if tg>c then tg:=c;
 min:=tg;
end;
{--------------------------------------------------}
function cottr(c:integer):integer;
begin
 if c<=1 then cottr:=1 else cottr:=c-1;
end;
{---------------------------------------------------}
function cotph(c:integer):integer;
begin
 if c>=1 then cotph:=m else cotph:=c+1;
end;
{----------------------------------------------------}
procedure process;
var i,j:integer;
begin
 for j:=1 to m do L[1,j]:=p+a[1,j];
 for i:=2 to n do
 for j:=1 to m do
 L[i,j]:=max(L[i-1,cottr(j)],L[i-1,j],L[i-1,cotph(j)])+a[i,j];
 Hmax:=L[n,1];
 for j:=1 to m do
 if a[1,j]=0 then L[1,j]:=p-p div 2 else L[1,j]:=p+a[1,j];
 for i:=2 to n do
 for j:=1 to m do
 begin
 L[i,j]:=min(L[i-1,cottr(j)],L[i-1,j],L[i-1,cotph(j)])+a[i,j];
 if a[i,j]=0 then L[i,j]:=L[i,j]-L[i,j] div 2;
 end;
 Hmin:=L[n,1];
 for j:=2 to m do
 if Hmin>L[n,j] then Hmin:=L[n,j];
end;
{----------------------------------------------------}
procedure outputdata;
var f:text;
begin
 assign(f,fo);
 rewrite(f);
 writeln(f,Hmin);
 writeln(f,Hmax);
 close(f);
end;
{--------------------------------------------------------------}
BEGIN
 inputdata;
 process;
 outputdata;
END.
2.4. HIỆU QUẢ CỦA SÁNG KIẾN KINH NGHIỆM ĐỐI VỚI HOẠT ĐỘNG GIÁO DỤC, VỚI BẢN THÂN, ĐỒNG NGHIỆP VÀ NHÀ TRƯỜNG
Với sáng kiến kinh nghiệm này, theo ý kiến chủ quan của bản thân tôi nhận thấy đã đóng góp được một phần nhỏ vào công tác bồi dưỡng học sinh giỏi môn tin học tại đơn vị công tác của mình- Trường THPT Hàm Rồng. Giúp trang bị thêm kiến thức cho các em học sinh trong đội tuyển Tin để các em có được động lực, sự tự tin để học tốt hơn. Giúp các đồng nghiệp có thêm tài liệu tham khảo, cùng nhau tự học, tự bồi dưỡng. 
3. KẾT LUẬN, KIẾN NGHỊ
Hệ thống lý thuyết và một số bài tập về quy hoạch động được đưa ra để học sinh có thể luyện tập và nâng cao kỹ năng lập trình của mình phải tương đối lớn và được lựa chọn thật kỹ càng, thêm nữa các bài toán phải được phân loại và tập hợp thành những module cụ thể, điều này sẽ gây hứng thú hơn cho học sinh trong quá trình nghiên cứu và vận dụng. Tuy nhiên, do thời gian có hạn nên trong đề tài chỉ mới đưa ra một số ít các bài toán về quy hoạch động.
Mặc dù bản thân đã cố gắng nhiều, song trong đề tài còn nhiều khiếm khuyết, tôi rất mong nhận được sự đóng góp ý kiến của các đồng nghiệp để hoàn thiện hơn và đạt hiệu quả trong giảng dạy và học tập của học sinh.
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./.
XÁC NHẬN CỦA HIỆU TRƯỞNG
Thanh Hoá, ngày 05 tháng 05 năm 2019
Tôi xin cam đoan đây là SKKN của bản thân viết, không sao chép nội dung của người khác.
Người viết đề tài
Nguyễn Thị Mai Hương
TÀI LIỆU THAM KHẢO
1. SGK Tin học 11- NXB Giáo Dục Việt Nam
2. SBT Tin học 11- NXB Giáo Dục Việt Nam
3. Tài liệu chuyên Tin học- Quyển 1- - NXB Giáo Dục Việt Nam
4. Internet
DANH MỤC CÁC ĐỀ TÀI SÁNG KIẾN KINH NGHIỆM ĐÃ ĐƯỢC ĐÁNH GIÁ
Họ và tên: Nguyễn Thị Mai Hương
Chức vụ công tác: Giáo viên
STT
TÊN ĐỀ TÀI
Cấp đánh giá xếp loại
NĂM HỌC
XẾP LOẠI
1
Một số bài toán bồi dưỡng HSG Tin học 11 về số nguyên tố.
Cấp Sở GD&ĐT
2014 - 2015
C
2
Một số bài toán bồi dưỡng HSG Tin học 11 về xử lí số nguyên lớn.
Cấp Sở GD&ĐT
2016 - 2017
C

Tài liệu đính kèm:

  • docskkn_mot_so_bai_toan_quy_hoach_dong_trong_boi_duong_hoc_sinh.doc