主题:第十一届全国青少年奥林匹克信息学联赛复赛提高组试题-谁拿了最多奖学金-文件输入常出现的问题,请看看!
怜丹欣∮
[专家分:120] 发布于 2007-07-17 08:13:00
[size=5][color=800000] 大家看看这道题,我做过了,原理很简单,可就是输入的时候有点问题,题要求先读名字,再读其它的,这就不免回用到字符串(也可不用,用s:array[1..n]of char),总之是输入的时候用字符串会将后面的一起读进去,请问大家该怎么解决?谢谢!!下面是原题:[/color][/size]
第十一届全国青少年奥林匹克信息学联赛复赛提高组试题
发布日期: 2005-11-21 访问总次数: 20298
(提高组 三小时完成)
谁拿了最多奖学金
(scholar.pas/c/cpp)
【问题描述】
某校的惯例是在每学期的期末考试之后发放奖学金。发放的奖学金共有五种,获取的条件各自不同:
1)院士奖学金,每人8000元,期末平均成绩高于80分(>80),并且在本学期内发表1篇或1篇以上论文的学生均可获得;
2)五四奖学金,每人4000元,期末平均成绩高于85分(>85),并且班级评议成绩高于80分(>80)的学生均可获得;
3)成绩优秀奖,每人2000元,期末平均成绩高于90分(>90)的学生均可获得;
4)西部奖学金,每人1000元,期末平均成绩高于85分(>85)的西部省份学生均可获得;
5)班级贡献奖,每人850元,班级评议成绩高于80分(>80)的学生干部均可获得;
只要符合条件就可以得奖,每项奖学金的获奖人数没有限制,每名学生也可以同时获得多项奖学金。例如姚林的期末平均成绩是87分,班级评议成绩82分,同时他还是一位学生干部,那么他可以同时获得五四奖学金和班级贡献奖,奖金总数是4850元。
现在给出若干学生的相关数据,请计算哪些同学获得的奖金总数最高(假设总有同学能满足获得奖学金的条件)。
【输入文件】
输入文件scholar.in的第一行是一个整数N(1 <= N <= 100),表示学生的总数。接下来的N行每行是一位学生的数据,从左向右依次是姓名,期末平均成绩,班级评议成绩,是否是学生干部,是否是西部省份学生,以及发表的论文数。姓名是由大小写英文字母组成的长度不超过20的字符串(不含空格);期末平均成绩和班级评议成绩都是0到100之间的整数(包括0和100);是否是学生干部和是否是西部省份学生分别用一个字符表示,Y表示是,N表示不是;发表的论文数是0到10的整数(包括0和10)。每两个相邻数据项之间用一个空格分隔。
【输出文件】
输出文件scholar.out包括三行,第一行是获得最多奖金的学生的姓名,第二行是这名学生获得的奖金总数。如果有两位或两位以上的学生获得的奖金最多,输出他们之中在输入文件中出现最早的学生的姓名。第三行是这N个学生获得的奖学金的总数。
【样例输入】
4
YaoLin 87 82 Y N 0
ChenRuiyi 88 78 N Y 1
LiXin 92 88 N N 0
ZhangQin 83 87 Y N 1
【样例输出】
ChenRuiyi
9000
28700
最后更新于:2007-07-17 08:15:00
回复列表 (共13个回复)
沙发
abcwuhang [专家分:1840] 发布于 2007-07-17 11:59:00
由于程序数据范围只有100,当中不牵涉到数据移动,所以用一个纪录型数组,或者多个数组均可,在这里我们使用纪录型来描述。
对于输入数据有两种方式来实现。
法一〉逐个字符累加。
首先定义C:char; 然后利用Until c=‘ ’;作为终止符,将读入的字符连接存储到a[i].name中。
代码为:
Repeat read(c); a[i].name:=a[i].name+c; until c=’ ‘;
a[i].name:=copy(a[i].name,1,length(a[i].s)-1);
这样做的好处是,后面的值可以直接用read语句读入。但是最后一个值后,要记得readln;
法二〉一次读入,然后分离。
这样做需要逐个分离,对本题来说稍显复杂,但对NOIP来说此方法必须掌握,有的时候一定要用。
具体实现,读入一个字符串S。利用pos(‘ ‘,s);找出空格位置。再利用Copy函数,和Val函数进行截取,和转换。
部分代码:(s:string;j,ok:integer)
readln(s);
j:=pos(‘ ‘,s);
a[i].name:=copy(s,1,j-1);
s:= copy(s,j+1,50); //当长度〉字符串长度是,为后面全部截取。
j:=pos(‘ ‘,s);
Val(copy(s,1,j-1),a[i].qp,ok);
s:= copy(s,j+1,50);
…..
对于符号用if语句作一下判断就是了,太easy不写了,后面还有几个值,用同样方法处理就可以了。
板凳
怜丹欣∮ [专家分:120] 发布于 2007-07-17 16:13:00
第一种:
Repeat read(c); a[i].name:=a[i].name+c; until c=’ ‘;
a[i].name:=copy(a[i].name,1,length(a[i].[color=800000][size=4]s[/size][/color])-1);请问这里的S是怎么回事?也就是说a[i].name:=copy(a[i].name,1,length(a[i].[color=800000][size=4]s[/size][/color])-1);[/color]有什么用的?
第二种:
还有就是这段程序我没懂:
......
s:= copy(s,j+1,50); //当长度〉字符串长度是,为后面全部截取。
j:=pos(‘ ‘,s);
Val(copy(s,1,j-1),a[i].qp,ok);
s:= copy(s,j+1,50);
......
请再详细地讲一下,谢谢!!
3 楼
maxumi [专家分:2200] 发布于 2007-07-17 16:19:00
copy(st,m,n)就是从字符串st的第m位开始取n位
比如copy('ABCabc', 2, 4)就是'BCab'
4 楼
maxumi [专家分:2200] 发布于 2007-07-17 16:22:00
[quote]第一种:
Repeat read(c); a[i].name:=a[i].name+c; until c=’ ‘;
a[i].name:=copy(a[i].name,1,length(a[i].[color=800000][size=4]s[/size][/color])-1);请问这里的S是怎么回事?也就是说a[i].name:=copy(a[i].name,1,length(a[i].[color=800000][size=4]s[/size][/color])-1);[/color]有什么用的?
[/quote]
这个我估计是他用了个记录类型,a[i].name 是名字, a[i].s是整个一行字符串
不过看起来貌似还有些问题......
5 楼
Matodied [专家分:7560] 发布于 2007-07-17 21:31:00
最头疼的就是这个名字是几个字符的问题,由于没有办法知道每个人的名字是几个字符,所以只能从右往左取。
这里要分5步:
第1步:取最后的2个字符(因为论文总数最多2位数),如果第一个是空格,就舍弃。
第2步:用DELETE剔除这个字符串的后2位,剩余字符串取最后一位,就是这个学生是不是西部的人的标志。
第3步:再剔除余串的最后2位,余串取最后1位,就是这个学生是不是干部的标志。
第4步:再剔除余串的最后2位,这里可有点难受:
必须从余串最后一个字符开始取到发现的空格为止。就是这个人的班级评议成绩。
第5步:这里和第4步一样,取出来的数为期末考试成绩,我就不说了。
接着再去掉这个成绩的字符就是名字了。
我们可以设立以下6个变量:
name: STRING {这个人的名字}
test_score: INTEGER {这个人的期末考试成绩}
class_score: INTEGER {这个人的班级评议成绩}
is_monitor: BOOLEAN {这个人是不是干部}
is_western: BOOLEAN {这个人是不是西部的}
composition: INTEGER {这个人发表的论文总数}
接着可以知道这个人获得了哪些奖学金。
money := 0;
IF (test_score > 80) AND (composition >= 1) THEN money := money + 8000; {院士奖学金}
IF (test_score > 85) AND (class_score > 80) THEN money := money + 4000; {五四奖学金}
IF (test_score > 90) THEN money := money + 2000; {成绩优秀奖}
IF (test_score > 85) AND (is_western) THEN money := money + 1000; {西部奖学金}
IF (class_score > 80) AND (is_monitor) THEN money := money + 850;
{班级贡献奖}
6 楼
怜丹欣∮ [专家分:120] 发布于 2007-07-18 08:59:00
谢谢!5楼的方法很有创意!
有谁能解决2楼的问题?
7 楼
abcwuhang [专家分:1840] 发布于 2007-07-18 11:54:00
改一下:S改为NAME.
不小心打错了~~~
8 楼
怜丹欣∮ [专家分:120] 发布于 2007-07-18 11:57:00
请7楼的abcwuhang再帮我讲一下你的第二种方案,谢谢!
9 楼
abcwuhang [专家分:1840] 发布于 2007-07-18 11:59:00
讲评:
部分代码:(s:string;j,ok:integer)
readln(s);{读入字符串}
j:=pos(‘ ‘,s);{找出第一个空格位置,它之前是名字,它之后是内容}
a[i].name:=copy(s,1,j-1);{把名字赋值到a[i].name中}
s:= copy(s,j+1,50); //当长度>字符串长度是,为后面全部截取。{把空格位置之前的东东(名字)删除,为找成绩做准备}
j:=pos(‘ ‘,s);{再找空格位置,即是第一个成绩和第二个成绩之间的位置}
Val(copy(s,1,j-1),a[i].qp,ok);{把成绩赋值到ok中}
s:= copy(s,j+1,50);{把空格位置之前的成绩删除,为后一轮的找成绩作准备}
…..类似重复上面的,直到把数据全部输入完毕
10 楼
怜丹欣∮ [专家分:120] 发布于 2007-07-18 12:06:00
为什么"s:= copy(s,j+1,50);"这里是50?
val的用法是怎么样的?也就是说请举个例子,比如将'86'这个字符串转换到a[i].qm中去.
我来回复