T1
题目描述
镇海中学开设了很多校本选修课程,有体育类、音乐类、美术类、无线电测向、航空 航海航天模型制作等,力争使每位学生高中毕业后,能学到一门拿得出手的兴趣爱好,为将来的终身发展打下基础。在体育类的校本选修课程中,有一门课程是斯诺克台球。
斯诺克台球比赛中有21个球,其中有15个红球,6个彩球(黄、绿、棕、蓝、粉、黑)。甲乙二人轮流打球。打一个红球得1分,打一个彩球的得分如下:
黄球:2分; 绿球:3分; 棕球:4分;
蓝球:5分; 粉球:6分; 黑球:7分;
最后以得分高者为胜。
简化后的打球规则如下:
1.如果有红球,第奇数次必须打红球,打过的红球从桌面上拿走;
2.每打一个红球后,可以任意选一个彩球打,打红球后接着打的彩球不从桌面上拿走;
3 如果桌面上已经没有红球可打了,那么按照分值从小到大的次序打彩球,这时候每打一个彩球都从桌面上拿走。
打球时犯规的判罚如下:
1.没有打中球,给对方加4分;
2.没有按照打球规则打该打的球,即打中了错误的球时:
(1)如果这个错误的球的分值大于4,那么给对方加等于这个球的分值;
(2)如果这个错误的球的分值不大于4,那么给对方加4分;
打中的错误球不从桌面上拿走。
请统计某局比赛进行到现在为止的比分。
思路:模拟,没啥好说。。。
代码:
uses math;
var n,m,x,t,t1,i,red,colourful:longint;
begin
assign(input,'snooker.in');
assign(output,'snooker.out');
reset(input);
rewrite(output);
read(n,m);
red:=15;
colourful:=1;
for i:=1 to n-1 do
begin
read(x);
if x=1 then dec(red) else
if (red=0)and((i mod 2=1)or(colourful>1)) then inc(colourful);
t:=t+x;
end;
read(x);
inc(i);
if (red=0)and((i mod 2=1)or(colourful>1)) then inc(colourful);
if x=0 then t1:=t1+4 else
if (red=0)and(x<>colourful) then t1:=t1+max(4,x) else
if (n mod 2=1)and(x>1)and(red<>0) then t1:=t1+max(4,x) else
if (n mod 2=0)and(x=1) then t1:=t1+4 else
t:=t+x;
x:=t1; t1:=t; t:=x;
for i:=1 to m-1 do
begin
read(x);
if (x=1) then dec(red) else
if (red=0)and((i mod 2=1)or(colourful>1)) then inc(colourful);
t:=t+x;
end;
read(x);
inc(i);
if (red=0)and((i mod 2=1)or(colourful>1)) then inc(colourful);
if x=0 then t1:=t1+4 else
if (red=0)and(x<>colourful) then t1:=t1+max(4,x) else
if (m mod 2=1)and(x>1)and(red<>0) then t1:=t1+max(4,x) else
if (m mod 2=0)and(x=1) then t1:=t1+4 else
t:=t+x;
if x=1 then dec(red);
write(t1,' ',t);
close(input);
close(output);
end.
T2
现在有n个人,每个人都有一个智力值和能力值。对于某一个人A来说,如果其它n-1个人中,没有人的智力值和能力值都比A高,则我们称A为“牛人”。反过来说,只要有一个人的智力值和能力值都比A高,则A就不是“牛人”了。
请统计共有多少个“牛人”。
思路:
可以看成平面直角坐标系,只要没有点在他右上角,则此店是牛人。
代码:
var a,b:array[-10..100010] of longint;
n,i,j,ans:longint;
f:array[-10..100010] of boolean;
t:boolean;
procedure qsort(l,r:longint);
var i,j,mid:longint;
begin
if l>=r then exit;
i:=l; j:=r; mid:=a[(i+j) div 2];
repeat
while a[i]<mid do inc(i);
while a[j]>mid do dec(j);
if i<=j then
begin
a[0]:=a[i]; a[i]:=a[j]; a[j]:=a[0];
b[0]:=b[i]; b[i]:=b[j]; b[j]:=b[0];
inc(i); dec(j);
end;
until i>=j;
qsort(l,j);
qsort(i,r);
end;
begin
assign(input,'niuren.in');
assign(output,'niuren.out');
reset(input);
rewrite(output);
read(n);
for i:=1 to n do read(a[i]);
for i:=1 to n do read(b[i]);
for i:=1 to n do
begin
t:=true;
if f[i] then continue;
for j:=n downto 1 do
begin
if (a[i]>a[j])and(b[i]>b[j]) then f[j]:=true else
if (a[j]>a[i])and(b[j]>b[i]) then
begin
t:=false;
break;
end;
end;
if t then inc(ans);
end;
write(ans);
close(input);
close(output);
end.
T3
题目描述
今年是镇海中学的百年校庆。校庆演出时,导演需要一列连续的身高递增的学生来演出一个节目。现在有一列连续排列的学生,可以从这些学生中筛选掉最多一段连续的几个学生。然后从剩下的学生中,选出连续的若干个,这些学生的身高依次连续递增。
求可以得到的身高连续递增队列的最大长度?。
思路:
dp。f[i][0..1]表示前i人是否去掉了某一段的最大值。
代码:
uses math;
var n,i,j,ans:longint;
a:array[-10..5010] of longint;
f:array[-10..5010,0..1] of longint;
begin
assign(input,'queue.in');
assign(output,'queue.out');
reset(input);
rewrite(output);
read(n);
for i:=1 to n do read(a[i]);
for i:=1 to n do
begin
if a[i]>a[i-1] then
begin
f[i,0]:=f[i-1,0]+1;
f[i,1]:=f[i-1,1]+1;
end else begin f[i,0]:=1; f[i,1]:=1; end;
for j:=1 to i-2 do
if a[j]<a[i] then f[i,1]:=max(f[j,0]+1,f[i,1]);
ans:=max(f[i,0],ans);
ans:=max(f[i,1],ans);
end;
write(ans);
close(input);
close(output);
end.
T4
题目描述
2011年3月16日以来,利比亚爆发的骚乱不断升级,已严重危及到普通民众和各国在利比亚工作的人员的安全。为了尽快救出在利比亚的同胞,根据利比亚的形势,我国政府告诉每个在利比亚的公民,如何行动才能最快地到达安全的地方,然后由我国派出的飞机、轮船、汽车接回国。
假设将利比亚的地图划分为一个n行m列的长方形,待拯救的同胞小A在1行1列处,安全的目标位置在n行m列处。
利比亚是一个多沙漠的国家,经过某些位置需要消耗一定数量的食品,某些位置存储有很多很多食品。假定小A现在在位置i行j列,如果身上带有足够在新位置处需要消耗的食品的话,小A的下一个位置将到达i-1行j列、i+1行j列、i行j-1列、i行j+1列这四个位置之一,如果新位置处有食品的话,小A最多能拿一份该位置处的食品。当然如果小A已有的食品加上新位置处的一份食品数量超过小A能带食品的最高上限,小A就不能拿该位置处的食品了。
如果身上的食品不够到下一位置处的消耗,小A就不能到下一位置去,否则会面临生命危险的。当然,小A可以数次经过同一个位置,每次到此位置,都需要先消耗食品,然后可以拿一份食品(如果有的话),也就是小A可以多次到同一个地方来攒食品,也可以多次到同一个地方来消耗食品。若一个位置既要消耗食品,又可以拿食品,则小A必须先消耗食品,然后才能拿一份食品。
给出利比亚的地图,请告诉小A如何最快地从起点(1,1)走到终点(n,m)。程序只要输出最短路径长度就可以了。
思路:
记忆化搜索。f[i,j,k]表示到ij食物为k的最短路。
代码:
var a,b:array[0..201,0..201] of longint;
f:array[0..201,0..201] of boolean;
i,j,n,m,t,code,maxc,k,x,y,w:longint;
c:char;
procedure dfs(x,y,dep:longint);
begin
if not f[x,y] then exit;
if dep>=b[x,y] then exit;
b[x,y]:=dep;
dfs(x+1,y,dep+1);
dfs(x-1,y,dep+1);
dfs(x,y+1,dep+1);
dfs(x,y+1,dep+1);
end;
begin
assign(input,'libyan.in');
assign(output,'libyan.out');
reset(input);
rewrite(output);
readln(n,m,t,maxc);
for i:=1 to n do
begin
for j:=1 to m do
begin
read(c);
if c<>'*' then f[i,j]:=true;
if (c<>'*')and(c<>'.') then a[i,j]:=ord(c)-48;
end;
readln;
end;
readln(k);
for i:=1 to k do begin read(x,y,w); end;
fillchar(b,sizeof(b),127);
dfs(1,1,0);
write(b[n,m]);
close(input);
close(output);
end.
T5
题目描述
FJ 决定用他现有牛群的数据来制造一个自动分类机;它能猜测牛身上有没有斑点。不幸的是,FJ 没有很好的数据。对于他的N 头牛,他所知道的仅仅只是牛的重量,以及这头牛是否有斑点。所有的牛都有不同的重量。为了猜测一个新牛C 是否有斑点,FJ 先找到现有牛群中和新牛重量最接近的牛C’。如果这头牛有斑点,FJ 猜测新牛也有斑点;反之,新牛没有斑点。如果有两头牛和新牛重量差相等,如果有其中之一的牛有斑点,那么FJ 就猜测新牛也有斑点。FJ 用他的这种测试机在新进的一群牛身上。这批牛重量(连续整数)都在A 和B 之间(包含A;B)。请帮助他决定其中有多少牛会被分类为有斑点。注意新的机器只会从FJ 现有的牛群中比较数据,不会在他任何新牛中比较。还有注意,由于A 和B 都可能很大,你的程序如果从A B 一个一个的循环很可能跑不快。
思路:
分类讨论,注意边界情况。
代码:
uses math;
var a:array[0..50011] of longint;
f:array[0..50011] of boolean;
n,l,r,ans,t1:longint;
procedure qsort(l,r:longint);
var i,j,mid:longint;
begin
if l>=r then exit;
i:=l; j:=r; mid:=a[(i+j) div 2];
repeat
while a[i]<mid do inc(i);
while a[j]>mid do dec(j);
if i<=j then
begin
a[0]:=a[i]; a[i]:=a[j]; a[j]:=a[0];
f[0]:=f[i]; f[i]:=f[j]; f[j]:=f[0];
inc(i); dec(j);
end;
until i>=j;
qsort(l,j);
qsort(i,r);
end;
procedure init;
var st:string;
code,i,t:longint;
begin
readln(n,l,r);
for i:=1 to n do
begin
readln(st);
t:=pos(' ',st);
if copy(st,1,t-1)='S' then f[i]:=true;
val(copy(st,t+1,length(st)),a[i],code);
end;
qsort(1,n);
t1:=1;
while a[t1]<l do inc(t1);
end;
procedure main;
var i,j,t:longint;
begin
a[0]:=0;
f[0]:=false;
if (f[t1])and(f[t1-1]) then ans:=ans+(a[t1]-l) else
if f[t1-1] then
begin
t:=(a[t1]-a[t1-1]) div 2;
if(a[t1-1]+t>=l) then
ans:=ans+(a[t1-1]+t-l+1);
end else
if f[t1] then
begin
t:=(a[t1]-a[t1-1])div 2;
if(a[t1]-t>=l)then ans:=ans+t else
ans:=ans+a[t1]-l;
end;
i:=t1+1;
while(i<n)and(a[i]<r) do
begin
if (f[i-1])and(f[i]) then ans:=ans+a[i]-a[i-1] else
if f[i-1] then
begin
ans:=ans+(a[i]-a[i-1])div 2+1;
end else
if f[i] then
begin
ans:=ans+(a[i]-a[i-1])div 2;
end;
inc(i);
end;
if f[i-1] and f[i] then ans:=ans+r-a[i-1]+1 else
if f[i-1] then
begin
t:=(a[i]-a[i-1])div 2;
if a[i-1]+t>r then ans:=ans+r-a[i-1]+1 else
ans:=ans+t+1;
end else
if f[i] then
begin
t:=(a[i]-a[i-1])div 2+1;
if a[i]-t+1<=r then ans:=ans+r-a[i]+t;
end;
end;
begin
assign(input,'learning.in');
assign(output,'learning.out');
reset(input);
rewrite(output);
init;
main;
write(ans);
close(input);
close(output);
end.