全国信息学奥林匹克联赛(NOIP 2007)复赛题目



全国信息学奥林匹克联赛(NOIP 2007)复赛题目

NOIP2007第十三届全国青少年信息学奥林匹克联赛复赛试题普及组

 

普及组

 

 

题目一览

 

题目名称 奖学金 纪念品分组 守望者的逃离 Hanoi双塔问题
代号 scholar group escape hanoi
输入文件 scholar.in group.in escape.in hanoi.in
输出文件 scholar.out group.out escape.out hanoi.out
时限 1秒 1秒 1秒 1秒

 

 

(20071117日  3小时完成)

 

 

说明:

1. 文件名(程序名和输入输出文件名)必须使用小写

2. C/C++中函数main()的返回值类型必须是int,程序正常结束时的返回值必须是0

3. 全国统一评测时采用的机器参考配置为:CPU 2.0GHz,内存256M

 


1.奖学金

(scholar.pas/c/cpp)

 

【问题描述】

某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金。期末,每个学生都有3门课的成绩:语文、数学、英语。先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序,如果两个同学总分和语文成绩都相同,那么规定学号小的同学排在前面,这样,每个学生的排序是唯一确定的。

任务:先根据输入的3门课的成绩计算总分,然后按上述规则排序,最后按排名顺序输出前5名学生的学号和总分。注意,在前5名同学中,每个人的奖学金都不相同,因此,你必须严格按上述规则排序。例如,在某个正确答案中,如果前两行的输出数据(每行输出两个数:学号、总分)是:

7 279

5 279

这两行数据的含义是:总分最高的两个同学的学号依次是7号、5号。这两名同学的总分都是279(总分等于输入的语文、数学、英语三科成绩之和),但学号为7的学生语文成绩更高一些。如果你的前两名的输出数据是:

5 279

7 279

则按输出错误处理,不能得分。

【输入】

输入文件scholar.in包含n+1行:

第1行为一个正整数n,表示该校参加评选的学生人数。

2n+1行,每行有3个用空格隔开的数字,每个数字都在0100之间。第j行的3个数字依次表示学号为j-1的学生的语文、数学、英语的成绩。每个学生的学号按照输入顺序编号为1~n(恰好是输入数据的行号减1)。

所给的数据都是正确的,不必检验。

【输出】

输出文件scholar.out共有5行,每行是两个用空格隔开的正整数依次表示前5名学生的学号和总分。

 

【输入输出样例1】

scholar.in scholar.out
6

90 67 80

87 66 91

78 89 91

88 99 77

67 89 64

78 89 98

6 265

4 264

3 258

2 244

1 237

 

【输入输出样例2】

scholar.in scholar.out
8

80 89 89

88 98 78

90 67 80

87 66 91

78 89 91

88 99 77

67 89 64

78 89 98

8 265

2 264

6 264

1 258

5 258

 

 

【限制】

50%的数据满足:各学生的总成绩各不相同

100%的数据满足:6<=n<=300

 


2纪念品分组

(group.pas/c/cpp)

 

【题目描述】

元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作。为使得参加晚会的同学所获得的纪念品价值相对均衡,他要把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品,并且每组纪念品的价格之和不能超过一个给定的整数。为了保证在尽量短的时间内发完所有纪念品,乐乐希望分组的数目最少。

你的任务是写一个程序,找出所有分组方案中分组数最少的一种,输出最少的分组数目。


 

【输入】

输入文件group.in包含n+2行:

1行包括一个整数w,为每组纪念品价格之和的上限。

2行为一个整数n,表示购来的纪念品的总件数。

3~n+2行每行包含一个正整数pi (5 <= pi <= w),表示所对应纪念品的价格。

 

【输出】

输出文件group.out仅一行,包含一个整数,即最少的分组数目。

 

【输入输出样例】

group.in group.out
100

9

90

20

20

30

50

60

70

80

90

6

 

【限制】

50%的数据满足:1 <= n <= 15

100%的数据满足:1 <= n <= 30000, 80 <= w <= 200

 


3守望者的逃离

(escape.pas/c/cpp)

 

【问题描述】

恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变。守望者在与尤迪安的交锋中遭遇了围杀,被困在一个荒芜的大岛上。为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很快就会沉下去。到那时,岛上的所有人都会遇难。守望者的跑步速度为17m/s,以这样的速度是无法逃离荒岛的。庆幸的是守望者拥有闪烁法术,可在1s内移动60m,不过每次使用闪烁法术都会消耗魔法值10点。守望者的魔法值恢复的速度为4/s,只有处在原地休息状态时才能恢复。

现在已知守望者的魔法初值M,他所在的初始位置与岛的出口之间的距离S,岛沉没的时间T。你的任务是写一个程序帮助守望者计算如何在最短的时间内逃离荒岛,若不能逃出,则输出守望者在剩下的时间内能走的最远距离。注意:守望者跑步、闪烁或休息活动均以秒(s)为单位,且每次活动的持续时间为整数秒。距离的单位为米(m)

 

【输入】

输入文件escape.in仅一行,包括空格隔开的三个非负整数M, S, T。

【输出】

输出文件escape.out包含两行:

1行为字符串“Yes”或“No”(区分大小写),即守望者是否能逃离荒岛。

2行包含一个整数。第一行为“Yes”(区分大小写)时表示守望者逃离荒岛的最短时间;第一行为“No”(区分大小写)时表示守望者能走的最远距离。

 

【输入输出样例1

escape.in escape.out
39 200 4 No

197

 

【输入输出样例2

escape.in escape.out
36 255 10 Yes

6

 

【限制】

30%的数据满足:1 <= T <= 10, 1 <= S <= 100

50%的数据满足:1 <= T <= 1000, 1 <= S <= 10000

100%的数据满足:1 <= T <= 300000, 0 <= M <= 1000, 1 <= S <= 108.

 


4Hanoi双塔问题

(hanoi.pas/c/cpp)

 

【问题描述】

给定ABC三根足够长的细柱,在A柱上放有2n个中间有孔的圆盘,共有n个不同的尺寸,每个尺寸都有两个相同的圆盘,注意这两个圆盘是不加区分的(下图为n=3的情形)。现要将这些圆盘移到C柱上,在移动过程中可放在B柱上暂存。要求:

1)每次只能移动一个圆盘;

2ABC三根细柱上的圆盘都要保持上小下大的顺序;

任务:设An为2n个圆盘完成上述任务所需的最少移动次数,对于输入的n,输出An。

 

【输入】

输入文件hanoi.in为一个正整数n,表示在A柱上放有2n个圆盘。

【输出】

输出文件hanoi.out仅一行,包含一个正整数为完成上述任务所需的最少移动次数An。

 

【输入输出样例1

hanoi.in hanoi.out
1 2

 

【输入输出样例2

hanoi.in hanoi.out
2 6

 

【限制】

对于50%的数据,1<=n<=25

对于100%的数据,1<=n<=200

 

【提示】

设法建立An与An-1的递推关系式。