Noip 2010普及组解题报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
解析
1、数字统计
【思路分析】
这道题属于简单题,用一个FOR把数都检查一遍,里面再用while剥皮看看有多少个2。
【参考程序】
Var
I,n,l,r,s:integer;
Begin
Assign(input,’two.in’);
Assign(output,’two.out’);
Readln(l,r);
S:=0;
For i:=1 to r do
Begin
N:=I;
While n>0 do
Begin
If n mod 10=2 then s:=s+1;
N:=n div 10;
End;
End;
Writeln(s);
Close(input);close(output;)
End.
2、接水问题
【思路分析】
方法一:用一个数组,存放每个水龙头当前还需要多少时间装完这桶水;然后一个一个人去轮,每次找最快装完的水龙头,接着把当前轮到的那个人所需要的时间加到格子里;最后轮完以后,还要把数组里的最大值输出。
【参考程序】
Var
a:=array[1..10000]of integer;
b:=array[1..100]of longint;
m,n,i,k,t,max,min:longint;
begin
assign(input,'water.in');
assign(output,'water.out');
reset(input);rewrite(output);
readln(n,m);
for i:=1 to n do read(a[i]);
fillchar(b,sizeof(b),0);
max:=0;k:=1;
while(k<=n) do
begin
min:=maxlongint;t:=0;
for i:=1 to m do
if b[i]<min then
min:=b[i];
t:=i;
end;
b[t]:=b[t]+a[k];
k:=k+1;
if b[t]>max then max=b[t];
end;
writeln(max);
close(input);close(output);
end.
方法二:用一个数组,存放每个水龙头当前还需要多少时间装完这桶水,并按照时间长短从大到小安排好;然后一个一个去轮,显然最快装完的水龙头总是最后一个,这样只要把当前轮到的那个人所需的时间加到最后那个元素里,再把数组排序好(很明显,这里要用插入排序效率最高);最后只要输出数组第一个元素就可以了。
【参考程序】
Var
a:=array[1..10000]of integer;
b:=array[1..100]of longint;
m,n,i:integer;
procedure sort(x:longint);
var i,j:integer;
begin
j:=m-1;
while(j>0)and(b[j]<x)do j:=j-1;
for i:=m-1 downto j+1 do
b[i+1]:=b[i];
b[j+1]=x;
end;
begin
assign(input,'water.in');
assign(output,'water.out');
reset(input);rewrite(output);
readln(n,m);
for i:=1 to n do read(a[i]);
fillchar(b,sizeof(b),0);
for i:=1 to n do
begin
b[m]:=b[m]+a[i];
sort(b[m]);
end;
writeln(b[1]);
close(input);close(output);
end.
3.导弹拦截
【思路分析】
先算出没课导弹到两个系统的距离的平方,存入相应的数组,并按照到第一套系统的距离的平方从大到小排序好(本题最大数据有100000组,故需要用快速排序,否则会超时);再以第二套系统出发,刷新他的平方(如果新半径平方比旧的要大的话)。
注意,这题不用开放,因为开放以后再平方等于什么也没有做。
【参考程序】
var
a,b:array[1..100000]of longint;
x,y,x1,y1,x2,y2,n,min,i,max:longint;
procedure kp(1,r:longint);
var i,j,t1,t2:longint;
begin
i:=1;j:=r;t1:=a[i];t2:=b[i];
while i<j do
begin
while(i<j) and (a[j]<t1) do dec(j);
if i<j then
begin
a[i]:=a[j];b[i]:=b[j];inc(i) end;
while (i<j) and(a[i]>t1) do inc(i)
if i<j then begin a[j]:=a[i];
b[j]:=b[i];dec(j) end
end;
a[i]:=t1;b[i]:=t2;
if l<i-1 then kp(1,i-1);
if j+1<r then kp(j+1,r);
end;
begin
assign(input,'missile.in');
assign(output,'missile.out');
reset(input);rewrite(output);
readln(x1,y1,x2,y2);
readln(n);
for i:=1 to n do
begin
readln(x,y);
a[i]:=(x-x1)*(x-x1)+(y-y1)*(y-y1);
b[i]:=(x-x2)*(x-x2)+(y-y2)*(y-y2);
end;
kp(1,n);
min:=a[1];max:=0;
for i:=1 to n-1 do
begin
if b[i]>max then max:=b[i];
if a[i+1]+max<min then min:=a[i+1]+max;
end;
writeln(min);
close(input);close(output);
end.
4.三国游戏
【思路分析】
这道题是一道比较忽悠人的题。
我的程序的策略是:建立武将默契值的二维数组,对行或者列进行排序,让后找出每行或者列的第二个数中的最大值即为结果。
注意要用快排,如果用选择排序或者冒泡排序的话要超时。
我试了一下,不用快排能得90分。
小涵选一个将,计算机选一个将,小涵选将策略总是选武将默契值最大的两个将中的一个,而计算机总是将另一个将选走,然后小涵选与刚刚选中武将的默契值第二大的一个。
那么小涵从哪个武将开始选呢,选的武将的与其他武将的默契值第二大的数,比其他武将开始选默契值大二大的数最大的那个武将。
存在必胜策略。
【参考程序】
type arraytype=array[1..500,1..500] of longint;
var m,n,i,j,max,temp,l,k:longint;
a:arraytype;
procedure qsort(var a:arraytype;hang,lx,rx:longint);
var i,j,x,temp:longint;
begin
i:=lx;
j:=rx;
x:=a[hang,(i+j) div 2];
while i<=j do
begin
while a[hang,i]>x do inc(i);
while a[hang,j]<x do dec(j);
if i<=j then begin
temp:=a[hang,i];a[hang,i]:=a[hang,j];a[hang,j]:=temp;
inc(i);dec(j);end;
end;
if j>lx then qsort(a,hang,lx,j);
if i<rx then qsort(a,hang,i,rx);
end;
begin
assign(input,'sanguo.in');
assign(output,'sanguo.out'); reset(input);
rewrite(output);
read(n);
for i:=1 to n-1 do
for j:=i+1 to n do
begin
read(a[i,j]);
a[j,i]:=a[i,j];
end;
for i:=1 to n do
qsort(a,i,1,n);
for i:=1 to n do
if a[i,2]>max then max:=a[i,2]; writeln(1);
write(max);
close(input);
close(output);
end.。