Thực hiện chương trình của học sinh và so sánh kết quả.. - Giám khảo có thể sử dụng chương trình gợi ý dưới đây để tính toán kết quả của dữ liệu vào.. - Chương trình học sinh đúng một bộ
Trang 1Së GD&§T kú thi CHäN häc sinh giái cÊp tØnh líp 11 THPT Qu¶ng b×nh n¨m häc 2010 - 2011
M«n thi: tin häc
híng dÉn chÊm
I- Phương pháp:
- Giám khảo tạo bộ dữ liệu vào, tính toán kết quả Thực hiện chương trình của học sinh và so sánh kết quả
- Giám khảo có thể sử dụng chương trình gợi ý dưới đây để tính toán kết quả của dữ liệu vào
- Chương trình học sinh đúng một bộ test, giám khảo cho 0,5 điểm Như vậy, nếu một câu có 3 điểm thì giám khảo phải tạo 6 bộ test
- Với mỗi câu, giám khảo phải tạo được một bộ test có không gian dữ liệu lớn
- Đối với Câu 3 giám khảo phải tạo được 3 Test có M ≥ 60000 và N ≥ 70 và chấm thời gian thực hiện chương trình của học sinh
Bài ni nói ngắn gọn là tìm diện tích lớn nhất của các hình chữ nhật có giá trị trong
ô bằng nhau
Cách giải cho test nhỏ nì!
Sử dụng mảng A để lưu dữ liệu vào
Sử dụng 2 mảng 2 chiều: dong và cot
Dong để tính tổng các ô bằng nhau trên một dòng
Cot để tính tổng các ô bằng nhau trên một cột
(Tạm diễn đạt vậy đã, chưa hiểu thì tạm chấp nhận)
dong[i,j] = dong[i,j-1]+ 1 nếu a[i,j]=a[i,j-1]
Ví dụ, với i:=1
dong[1,j] = dong[1,j-1]+1 nếu a[1,j]=a[1,j-1]
Với test vào A như trên ta có mảng dong nì:
cot[i,j] = cot[i-1,j]+ 1 nếu a[i,j]=a[i-1,j]
Ví dụ, với j:=1
cot[i,1] = cot[i-1,1]+1 nếu a[i,1]=a[i-1,1]
Với test vào A như trên ta có mảng cot nì:
Sau đó chỉ cần tìm max của tích dong[i,j]*cot[i,j] là được thôi mà!
Để giải được cho bộ dữ liệu vào lớn như vậy, ta không thể sử dụng mảng hai chiều
để lưu được! Vì vậy phải vừa lưu vừa xử lý
Đó là tư tưởng của thuật toán trong HDC đó!
Trang 2Nếu ta sử dụng hai biên mảng DONG và COT thì không đủ bộ nhớ lưu trữ.
Bây chừ ta tìm cách để giảm biến mảng hè!
Giả sử ta phải lưu biến DONG mà không lưu biến COT có được không!
Giải quyết như thế nào!
Rõ ràng ta có thể không cần mảng COT nữa Khi đó
Nếu A[i,j] <> a[i-1,j] (nếu hai phần tử liên tiếp trên 1 cột khác nhau)
ddc:=1
Nếu A[i,j] = a[i-1,j] (nếu hai phần tử liên tiếp trên 1 cột bằng nhau)
ddc:=ddc+1
Nếu dientich<DONG*ddc then dientich :=DONG*ddc
Mà TT đó cửa I J thử áp dụng cho bộ test ni là sai rồi nì:
1 2 1 3 2
2 2 2 2 2
1 2 2 2 1
1 2 1 3 1
Khi đó mảng Dòng là:
1 1 1 1 1
1 2 3 4 5
1 1 2 3 1
1 1 1 1 1
mảng cột la:
1 1 1 1 1
1 2 1 1 2
1 3 2 2 1
2 4 1 1 2
Tổng kết:
1- Khi đọc một đề thi mà họ viết ”loằng ngằng” như cái đề trên kia, ta pahỉ tìm mô hình của bài toán đó! Mô hình là cái cối lõi, cái bản chất của bài toán!
2- Thường có hai dạng toán khó:
a) Dạng 1: Không gian dữ liệu rất lớn, đòi hỏi cấu trúc dữ liệu lưu trữ rất lớn!
b) Dạng 2: Số phép tính cần thực hiện rất lớn (giải quyết bài toán cần phải giải quyết nhiều bài toán con)
3- Cách giải quyết
a) Dạng 1: Tìm cách giảm cấu trúc lưu trữ Khí đó người ta nói phải sử dụng
kỹ thuật: ”Vừa đọc dữ liệu, vừa xử lý” Đương nhiên, có thể số phép toán bị tăng lên
Dạng 2: Tìm cách lưu trữ kết quả trung gian
2- Trong một số bài toán, ta nên giải quyết bắt đầu từ một thuận toán đơn giản Khi
đó cấu trúc dữ liệu cần lưu trữ sẽ là rất lớn!
Trang 3Anh làm như ri nì:
Nhận xét: Giả sử trên dòng 2 của mảng DONG,
nếu dong[2,j]=dong[2,j+1] thì A[2,j]=A[2,j+1]
(Nghĩa là giá trị của hai ô liên tục của A mà bằng nhau thì giá trị 2 ô liên tục của DONG là tăng dần (lên đúng 1 đơn vị)
Từ đó có TT:
- Nếu vị trí ta đang xét là [2,J] thì ta xác định xem bên trái ô [2,J] có phần tử bằng giá trị A[2,J]
- Nếu ô bên trái ô A[2,J] = A[2,J-1] thì ta xét xem số phần tử trên COT[2,J-1] có lớn hơn COT[2,J] không
+ Nếu COT[2,J-1] >= COT[2,J] thì ta lùi J-1 đơn vị để xét ô bên trái của ô [2,J-1]
Giới hạn để dừng lùi là COT[2,J-1] < COT[2,J]
Giả sử mảng A chỉ có một dòng
Khi đó để tìm HCN có diện tích lớn nhất như sau
Tại vị trí I ta xét sang phải,
While A[i]=A[i+1] do S:=S+1
Nếu SMax<S then Smax:=S
Lặp lại thì ta tìm được đoạn có nhiều phần tử nhất!
Đúng không nào!
1 1 2 1 3 S=2
Bây giờ ta thêm một dòng nữa được lưu trong mảng B
A 1 1 2 1 3
B 2 2 2 2 1
Như vậy mỗi phần tử trên mảng B nó còn có thêm một thuộc tính nữa, đó là ”chiều cao” của phần tử đó!
Ta định nghĩa: Chiều cao h của ô [i] là số lượng phần tử trên các dòng trước B có giá trị bằng ô B[i]
h 1 1 2 1 1
Khi xét một phần tử của mảng B, thì ta làm tương tự như trên mảng A kia, nhưng
ta còn phải xét đến độ cao của nó nữa!
II- Chương trình gợi ý:
Câu 1: (3,0 điểm) Sắp xếp xâu
Program Sap_xep;
Const fi='SAPXEP.inp';
fo='SAPXEP.out';
maxN=200;
Trang 4Type Rec= record
St:string;
sl:Byte;
end;
ArrRec = Array[0 MaxN] of Rec;
Var A:ArrRec;
N:Longint;
ch:Char;
Procedure Swap(Var Rec1,Rec2:Rec);
Var RecTg:Rec;
Begin
RecTg:=Rec1;
Rec1:=Rec2;
Rec2:=RecTg;
End;
Procedure Read_Data;
Var f:Text; i,j,d:Longint;
Begin
Assign(f,fi); Reset(f);
Readln(f,N);
for i:=1 to N do
Begin
Readln(f,A[i].St);
d:=0;
For j:=1 to Length(A[i].St) do
if ('0' <= A[i].St[j]) and (A[i].St[j]<='9') then
d:=d+1;
A[i].Sl:=d;
end;
Close(f);
End;
Procedure Sort;
Var i,j:Longint;
Begin
For i:= N Downto 2 do
For j:= 1 to i-1 do
if A[j].Sl > A[j+1].Sl then Swap(A[j],A[j+1]);
end;
Procedure Write_Data;
Var f:text;
i:Longint;
Begin
Assign(f,fo); Rewrite(f);
For i:=1 to N do
Writeln(f,A[i].St);
Close(f);
End;
BEGIN
Read_Data;
Sort;
Write_Data;
End.
Câu 2: (3,5 điểm) Số may mắn
program So_may_man;
Const fi='SOMM.inp';
fo='SOMM.out';
Var P,Q,K:Longint;
Procedure Read_Data;
Var f:Text;
Begin
Assign(f,fi); Reset(f);
Readln(f,P,Q,K);
Close(f);
End;
Function Sum(Num:Longint):Longint;
Trang 5Var T:Longint;
Begin
T:=0;
While Num>0 Do
Begin
T:= T + Num mod 10;
Num:= Num div 10;
End;
Sum:=T;
End;
Function Count:Longint;
Var D,i:Longint;
Begin
D:=0;
For i:=P to Q do
if Sum(i) mod K = 0 then
D:=D+1;
Count:=D;
End;
Procedure Write_Data;
var f:text;
Begin
Assign(f,fo); Rewrite(f);
Writeln(f,Count);
Close(f);
End;
BEGIN
Read_Data; Write_Data;
End.
Câu 3: (3,5 điểm) Hệ thống cảnh báo thảm họa
Const fi='HTCB.in7';
fo='HTCB.out';
MaxN=101;
Type Arr1=Array[0 MaxN] of Longint;
Var A,B,H:Arr1;
M,N,S:Longint;
f:Text;
Procedure Init;
Begin
Fillchar(A,sizeof(A),0);
Fillchar(B,sizeof(B),0);
Fillchar(H,sizeof(H),0);
S:=0;
Assign(f,fi);
Reset(f);
Readln(f,M,N);
End;
Procedure Read_Data;
Var i:Longint;
Begin
A:=B;
B[0]:=0;
B[N+1]:=0;
For i:=1 to N do
Read(f,B[i]);
Readln(f);
For i:=1 to N do
if B[i] = A[i] then
H[i]:=H[i] + 1
Else
H[i]:=1;
End;
Procedure Area;
Var i,Left,Right:Longint;
Begin
Trang 6For i:=1 to N do
Begin
Left:=i;
While (B[Left-1] = B[i]) And (H[Left-1]>=H[i]) do
Left:=Left-1;
Right:=i;
While (B[Right+1] = B[i]) And (H[Right+1]>=H[i]) do
Right:=Right+1;
if (Right - Left + 1)*H[i] > S then
S:=(Right - Left + 1)*H[i];
End;
End;
Procedure Solve;
Var i:Longint;
Begin
For i:=1 to M do
Begin
Read_Data;
Area;
End;
Close(f);
End;
Procedure Write_Data;
Var g:Text;
Begin
Assign(g,fo);
Rewrite(g);
Writeln(g,S);
Close(g);
End;
BEGIN
Init; Solve; Write_Data;
END.