08年的特长生(东莞)试题
一、聪明的小李
提交文件:num.pas / num.exe
问题描述:
小李的识记能力非常强,一列数他一看就知道最大的是哪个数,这个数在原数列中的位置。现在的问题是给定一个各不相同的正整数数列,要你找出第K大的数是多少,并指出该数在原数列中的位置。
数据输入:
从文件num.in中读入数据,文件共有三行,第一行是一个正整数N,表示原数列共有N个数,第二行是N个正整数,表示原数列中的每一个数。第三行是一个正整数,表示K的值。
数据输出:
结果输出到num.out中,共二行,第一行是一个整数,表示原数列中第K大的数,第二行是一个正整数,表示第K大数在原数列中的位置。
输入输出样例:
num.in
5
34 12 55 42 90
3
num.out
42
4
数据说明:N<=100,数列中所涉及到的数均在整型范围内。
思路:Wa,一看这题我一紧张,怎么会这么简单!其实很简单,入门都能AC,但是我恰好入坑了QAQ,第一次就WA了。WA的原因是“第K大”然而我做成了“第K小”。正确的代码如下:
var
a,b:array[0..101]of longint;
n,i,k,j,t,t1:longint;
begin
assign(input,'num.in');
assign(output,'num.out');
reset(input);
rewrite(output);
read(n);
for i:=1 to n do
begin
read(a[i]);
b[i]:=i;
end;
read(k);
for i:=1 to n-1 do
for j:=i to n do
begin
if a[i]<a[j] then begin
t:=a[i];
a[i]:=a[j];
a[j]:=t;
t1:=b[i];
b[i]:=b[j];
b[j]:=t1;
end;
end;
writeln(a[k]);
write(b[k]);
close(input);
close(output);
end.
(博主是一个大懒人,第二题一看高精就不做了)
三、奖金
提交文件:Reward.pas/reward.exe
【题目描述】
由于无敌的凡凡在2005年世界英俊帅气男总决选中胜出,Yali Company总经理Mr.Z心情好,决定给每位员工发奖金。公司决定以每个人本年在公司的贡献为标准来计算他们得到奖金的多少。
于是Mr.Z下令召开m方会谈。每位参加会谈的代表提出了自己的意见:“我认为员工a的奖金应该比b高!”Mr.Z决定要找出一种奖金方案,满足各位代表的意见,且同时使得总奖金数最少。每位员工奖金最少为100元。
【输入】
第一行两个整数n,m,表示员工总数和代表数;
以下m行,每行2个整数a,b,表示某个代表认为第a号员工奖金应该比第b号员工高。
【输出】
若无法找到合法方案,则输出“-1”;否则输出一个数表示最少总奖金。
输入输出样例
reward.in
2 1
1 2
reward.out
201
【数据范围】
80%的数据满足n<=1000,m<=2000;
100%的数据满足n<=10000,m<=20000。
思路:第三题一拿到,天哪!这是要用到邻接表的,然而我已经把它忘得一干二净了……后来在HJW大佬的帮助下解出来了,我理解到的是:邻接表作图、深搜、回溯、判断有无重复。好像很简单?是,但是我就是忘了邻接表,第一次想硬搜,或者用矩阵表示……不多说,贴代码:
var
f,a,b,next,list,cs:array[0..20001]of longint;
i,j,n,m,ans:longint;
procedure dfs(deep:longint);
var
i,j:longint;
begin
if cs[deep]>=2 then
begin
writeln('-1');
close(input);close(output);
halt;
end;
inc(cs[deep]);
i:=list[deep];
while i>0 do
begin
if f[deep]+1>f[a[i]] then begin
f[a[i]]:=f[deep]+1;
dfs(a[i]);
end;
i:=next[i];
end;
dec(cs[deep]);
end;
begin
assign(input,'reward.in');
assign(output,'reward.out');
reset(input);
rewrite(output);
read(n,m);
for i:=1 to m do
begin
read(a[i],b[i]);
next[i]:=list[b[i]];
list[b[i]]:=i;
end;
for i:=1 to n do f[i]:=100;
for j:=1 to n do dfs(j);
for i:=1 to n do ans:=ans+f[i];
write(ans);
close(input);close(output);
end.
四、工作
提交文件:Work.pas/work.exe
题目描述
这次故事的主角是HG!转眼4年过去了,HG本科毕业了,于是找了份工作。每天HG会收到一份任务清单,清单上列出了n个可能需要他完成的任务。每个任务包含3个信息:Ti、Ai、Bi,Ti表示完成此任务需要的时间,Ai表示此任务的到达时间,Bi表示此任务的最晚完成时间。在某一时刻若HG手上没有任务,那么他可以选择一个已经到达且还能够在Bi时刻之前(或者恰好在Bi时刻)完成的任务来做。
由于HG有点懒(纯属虚构:D),他想尽量少的减少他的总工作时间,但是他不能在可以做任务的时候故意不做(这样会被炒鱿鱼的>_<),那么他该如何挑选任务来做呢?
你的任务就是求出HG的最少工作时间(即总共有多少时间HG在做任务)。
数据输入:
从文件work.in读入数据,第一行一个整数n表示任务数。
以下n行,每行三个整数Ti,Ai,Bi。(n<=1000,0<=Ai,Bi<=1500,Ti>=1)
数据输出:
结果输出到work.out,输出仅一个数,即最少工作时间。
输入输出样例:
work.in
3
15 0 25
50 0 90
45 15 70
work.out
50
数据说明:
Ti>=1,0<=Ai,Bi<=1200;
30%的数据满足n<=5;60%的数据满足n<=500;100%的数据满足n<=1000。
输入数据保证Bi-Ai要大于等于Ti,且小于2Ti。
var
f:array[-1..1000]of longint;
Nt,Ar,Dl:array[-1..1000]of longint;
n,i,j,s,k:longint;
begin
read(n);
for i:=1 to n do
begin
read(Nt[i],Ar[i],Dl[i]);
f[i]:=Dl[i]-Nt[i];
end;
for i:=1 to n do
begin
j:=i+1;
if (f[i]<Nt[j])and(Nt[j]-f[i]>0) then begin
f[i]:=Nt[j]-f[i]; continue; end;
if (f[i]>=Nt[j]) then f[i]:=f[i];
end;
write(f[n]); writeln;
for i:=1 to n do write(f[i],' ');
end.