ACM校赛比赛题目及分析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Problem A -- 超级难题
Time Limit:1000ms Memory Limit:65535KB
Description
ACM程序设计大赛是大学级别最高的脑力竞赛,素来被冠以"程序设计的奥林匹克"的尊称。
大赛自1970年开始至今已有30年历史,是世界范围内历史最悠久、规模最大的程序设计竞赛。
比赛形式是:经过校级和地区级选拔的参赛组,于指定的时间、地点参加世界级的决赛,由3个成员组成的小组应用一台计算机解决6到8个生活中的实际问题。
参赛队员必须在5小时内编完程序并进行测试和调试。
此种大赛对参赛学生的逻辑分析能力、策略制定和脑力方面具有极大的挑战性。
大赛提倡在压力较大的情况下,培养学生的创造力、团队合作精神以解决竞赛的问题,从而挑选和发掘世界上最优秀的程序设计人才
竞赛的历史可以上溯到1970年,当时在美国德克萨斯A&M大学举办了首届比赛。
当时的主办方是the Alpha Chapter of the UPE Computer Science Honor Society。
作为一种全新的发现和培养计算机科学顶尖学生的方式,竞赛很快得到美国和加拿大各大学的积极响应。
1977年,在ACM计算机科学会议期间举办了首次总决赛,并演变成为目前的一年一届的多国参与的国际性比赛。
迄今已经举办了29届
ACM/ICPC以团队的形式代表各学校参赛,每队由3名队员组成。
每位队员必须是入校5年内的在校学生。
比赛期间,每队使用1台电脑需要在5个小时内使用C、C++、Pascal或Java中的一种编写程序解决8或10个问题。
程序完成之后提交裁判运行,并把运行结果及时通知参赛队。
而且有趣的是每队在正确完成一题后,组织者将在其位置上升起一只代表该题颜色的气球
2009年的时候队伍A参加了ACM的区域赛,那次区域赛比赛总共有N个题,队伍A做了N个题中的M个。
队伍A 做第一题所用的时间为T1分钟,做第一题所用的时间为T2分钟,.......做第M题所用的时间为Tm分钟。
求他们平均做一题所用的时间是多少分钟
Input
输入包含两行,第一行有两个数N,M(M<=N&&1<=N<=1000000)分别表示比赛的总题数和A队做的题数。
第二行有M个数,分别表示T1,T2.....Tm。
(1<=Ti<=1000000)
Output
输出他们平均做一题所用的分钟数(保留小数点后一位)
Sample Input
10 3
5 30 90
Sample Output
41.7
分析:所谓的“超级难题”事实上是一个超级水题,就是求平均数,前面一大段废话,可以直接略过。
可以说,只要热身题目搞定了,这个题肯定是能过的。
我们出去参加比赛的时候,有时候就能遇到A very hard problem其实就是水题,如果标题是A very easy problem嘿嘿~~那就要注意了,说不定就是个真正的“超级难题”
Problem B -- 灌水
Time Limit:1000ms Memory Limit:65535KB
Description
丁叔刚开始接触电脑就喜欢上了在论坛灌水。
虽然他经营农场很有那么一套,但是到了电脑面前就成了小白。
由于对电脑操作完全不熟悉,他总是找不到一种快速生成超长文本进行灌水的方法,每次都要在键盘上一个一个地敲入成百上千个字符。
终于,丁叔再也无法忍受了,花了一天的时间学习电脑,总算学会了复制、粘贴等基本操作的使用,假设丁叔敲入一个字符需要1个时间单位,复制任何连续的一段已输入的内容需要5个时间单位,粘贴一次需要2个时间单位,那么丁叔生成一段至少包含N个字符的文本最少需要多长时间?
Input
第一行表示测试用例的数目T
接下来T行每行一个整数N(1<=N<=10000)
Output
T行,每行一个正整数,表示生成相应长度至少为N的文本需要的最短的时间
Sample Input
2
6
15
Sample Output
6
14
分析:这是一个动态规划问题,我把sample分析一下,6直接输入6个字符就行。
15是先输入5个字符,复制,然后粘贴2次,总用时5+5+2+2=14
这是唯一没有人过的题。
注意复制一次后可以粘贴多次。
设f[i]是生成长度为i的文本所需要的最短时间,生成长度为i的文本有两种方式:1、在长度为i-1的文本后输入一个字符;2、复制长度为j (j<i)的文本,粘贴若干次。
特别注意题目要求的是“生成相应长度至少为N的文本需要的最短的时间”,“至少”,举个例子,如果要求的长度是14,我生成长度15的文本也是符合要求的。
状态转移方程可以这样写f[i] = min(f[i-1]+1, f[j] + times * 2 + 5)
Problem C -- 电子表格列序号转换
Time Limit:1000ms Memory Limit:65535KB
Description
电子表格软件中的表格是由一个个单元格组成,每个单元格都有它的坐标。
单元格的行坐标是由数字编号的数字序号,而列使用字母序号。
观察字母序号,发现第1列到第26列序号分别为A,B,…,Z,接着,第27列序号为AA,第28列为AB,依此类推
其中的规律不难发现:首先使用一位字母序号,按字典顺序排列,分别和开始的数字序号对应,然后使用两位字母,所有的组合按字典顺序和接下来的数字序号对应,然后使用三位字母…
现在请你编写一个程序,把数字序号转为字母序号,或者把字母序号转为数字序号
Input
第一行为一个整数N,表示接下来有多少组测试数据
第二行至第N+1行分别为N个测试数据,每行或者是一个整数,或者是一个仅由大写字母组成的字符串
Output
对每一行测试数据输出一行。
如果输入为一个整数,输出数字序号为此整数的列的字母序号;如果输入为字符串,输出字母序号为此字符串的列的数字序号
输入保证,所有数字序号和字母序号对应的数字序号均不超过2*10^9
Sample Input
2
27
AA
Sample Output
AA
27
分析:这就是一个进制转换的问题,10进制转26进制,26进制转10进制
Problem D -- 盛水的杯子
Time Limit:1000ms Memory Limit:65535KB
Description
如图所示,已知杯子的上半径R、下半径r以及高度H,往杯子里面倒一定容量的水,求水的高度
Input
第一行为一个整数T,代表测试用例的数目
接下来的T行,每一行一个测试用例,有四个double型的用空格分隔的数:r, R, H, V,分别代表杯子的下半径、上半径、高度以及倒入水的容量
数据范围:
T <= 20
1 <= r, R, H <= 100; 0 <= V <= 1000,000,000
r <= R
Output
对于每个测试用例,输出杯子中的水的高度。
保留6位小数
Sample Input
1
100 100 100 3141562
Sample Output
99.999024
分析:这是我们参加武大校赛的现场赛的题目,当时我们和很多人一样,将圆台补成圆锥,然后用大圆锥的体积减小圆锥的体积来计算高度。
这就不可避免的出现一个问题,当r和R相差很小的时候,补成的圆锥体积会非常大,然后相减就会产生很大的误差,造成精度损失,然后就W A了。
武大官方给的标程采用的是二分逼近的算法,利用圆台体积公式V = pi * (r * r + R * R + r * R) * h / 3,可以达到很高的精度
汤明同学用的补小圆锥的办法,但通过求比值的方法计算水的高度,巧妙地回避了因为减法导致的精度问题,这里特别拿出来说明一下,他的程序我也附在参考程序里面了
此外还有一个细节要注意:杯子水会溢出,最高的高度不会超过H
Description
维吉尼亚是一个经典的多表代替密码算法。
该算法使用一个词组作为密钥,密钥中的每一个字母用来确定一个代替表,每一个密钥字母用来加密一个明文字母:第一个密钥字母加密明文的第一个字母,第二个密钥字母加密明文的第二个字母,等所有的密钥字母使用完之后,密钥循环使用。
下面是维吉尼亚表
用一个例子来说明加密过程:假设明文为DA TASECRUITY,密钥为BEST,按照密钥的长度对明文做长度为4的分组,得到:DA TA SECU RITY。
对每个组用密钥BEST加密:在表中查询D行B列的值为E,为第一个密文字母,接下来查询A行E列的值为E,第二个密文字母就是E了,以此类推——得到密文EELTTIUNSMLR
Input
第一行为一个整数T,代表测试用例的数目
接下来的2T行,每行为不超过80个字符的字符串,只包括英文大写字母(没有空格)
第一行代表明文字符串,第二行代表密钥字符串
Output
输出共有T行,每行为对应明文加密后得到的密文
Sample Input
1
DA TASECURITY
BEST
Sample Output
EELTTIUNSMLR
分析:密码类的题目。
仔细观察矩阵可以发现规律,如果将A-Z编号为0-25,密文字母的编号就是明文字母的编号加上密钥字母的编号。
这样就变成了一个加法了,很容易做实现。
注意密钥是循环使用的,数据很弱,基本上能过sample 此题就能过
Description
长途坐车真难受,人们可能在车上早早睡着了,等到醒来的时候,车行驶到哪了?
假如长途车经过一些城镇,现在知道长途车行驶路线上相邻的城镇之间的距离和车从出发时算已经行驶的距离,请计算出汽车行驶到哪个城镇或哪两个城镇之间
Input
第一行是一个整数T,代表接下来有多少组数据
接下来是各组数据,每一组数据的第一行是两个整数N,M,分别表示城镇数目(包括起点和终点城镇)和要询问多少次到哪了。
接下来一行有N-1个整数,第i个数表示路线上第i个城镇(城镇从1开始编号,并且起始点为第1号)和第i+1个城镇之间的距离。
接下来一行有M个整数,表示M次询问到哪里时已经行驶的距离
一组测试数据中,城镇数不会超过10000个,两个城镇之间的距离不会超过100,询问次数不会超过100000
Output
对于每一组数据中的每一次询问,输出一行。
若汽车刚好行驶到某个城镇,则输出这个城镇的编号;若汽车行驶到两个城镇之间,输出两个城镇的编号,小编号先输出,大编号后输出,且用一个空格隔开
Sample Input
1
3 2
2 4
3 6
Sample Output
2 3
3
分析:本题就是一个查找。
此题有6个人过,我看过代码,都是用的顺序查找,时间复杂度为o(n)。
我特别设计了数据,专门卡这种做法,但数据还是不够强大(也许是服务器性能比较强大,囧一个先),虽然超时的很多,还是有6位同学通过优化过了-_-!!!。
本题我的参考程序使用的是二分查找,时间复杂度为o(logn)
Problem G -- 聪明的鸭子
Time Limit:1000ms Memory Limit:65535KB
Description
丁叔的家里以前养了一群奶牛。
但是为了社会的和谐,奔向小康。
丁叔又养了一群鸭子。
每天早上,他都从鸭舍C带着他的鸭群去农场中的A点觅食,然后去河边任意一点B让鸭子玩耍戏水,最后回到鸭舍C。
但是丁叔不止要照顾鸭群,还要去照看他的奶牛。
于是他把这率领鸭群的坚巨任务交给了一只聪明的鸭子。
这群鸭子很高兴能掌握决定路线的权利,为了能赶上每天下午的CC鸭V的新闻节目他们决定尽可能地减少路线的长度来保证从C点到A点到B点再回C点的路程最短。
现给出A、C两点的坐标,以及平行于X轴的河流的纵坐标。
B点为河流上任意一点,河流宽度不记,农场中无任何障碍物这使得鸭子可以在农场中的任意两点所连成的直线上毫无阻碍地移动。
求鸭子每天所走的最短路程
Input
第一行为一个整数T,代表测试用例的数目
接下来每一行都有5个数,用空格分开,分别为Ax,Ay,Cx,Cy,以及河流的纵坐标Z,其中(-5000<=Ax,Ay,Cx,Cy,Z<=5000且它们都为整数)
Output
输出鸭子每天走过的最短路程L,精确到小数点后4位
Sample Input
1
-1 2 2 2 0
Sample Output
8.0000
分析:这题我没啥说的了,水题,数据很弱。
放了个雷,鸭子是可以过河的,也就是说A和C是可以在河的两边的
Problem H -- 马踏棋盘
Time Limit:1000ms Memory Limit:65535KB
Description
在中国象棋中,马是按照“日”字的形状进行跳跃的。
对于一个给定的位置,马每次跳跃之后可以到达的位置如下图所示
其中圆圈所在位置为马跳跃前所在位置,三角所在位置为跳跃一次后可以达到的位置
现在给出一个大小为m行n列的棋盘,以及马所在的位置(a, b)和要到达的位置(c, d),求马从初始位置到终点位置需要跳跃的最少次数。
如果不可到达,则次数为0
Input
输入数据中第一行为一个整数k(0到50),表示后面测试用例的数目,每一组测试用例由2行组成,第一行为m, n两个正整数,第二行为a, b, c, d四个正整数
1 <= m, n <= 500
1 <= a, c <= m
1 <= b, d <= n
Output
对每个测试用例输出所需要的最少步数,如果不可达就输出0
Sample Input
2
5 5
1 1 3 2
10 10
2 2 5 8
Sample Output
1
3
分析:一个简单的广度优先搜索
Problem I -- 你也能解决
Time Limit:1000ms Memory Limit:65535KB
Description
很多人都知道小李同学进了阿里巴巴,虽然阿里不像Google或是Microsoft那么牛X,但在中国也算是一个很强大的公司,而且现在看来这个公司非常的有发展前途,如果真的某天所谓的“电子商务基础设施”由阿里搭建完成,想象一下,那个时候全世界的商人都将通过阿里巴巴做生意,那将会是一幅多么壮观的景象!前段时间小李同学到公司实习去了,在经过一个月的培训和一个月的非常紧张的项目实践后,他终于进入了部门。
他真的感到很高兴,因为部门的同事都和他一般大,大家都以同学互称,氛围很融洽。
当然,为了帮助小李同学更快的进步,公司给他分配了一个导师,说是导师,其实也才比他早一年进公司而已。
很快导师就给他分配了他的第一个正式的任务:
当用户搜索某个关键词keyword时,系统会先从一个数据源中取出和keyword相关的词,然后再从中取前至多21个推荐给用户,后来产品部门的人发现这个做法有待改进,可以每次随机的选取至多21个词,这样做可以使更多的页面被用户或是搜索引擎看到。
因此,小李同学的第一个任务就是把原来按顺序取的词变为随机地取。
怎么样,很简单吧!他接到这个任务后非常高兴,立即着手解决。
但他随即发现即使是这样一个简单的任务对他这个新人来说也是相当复杂的,摆在他面前的这个系统太庞大了,粗略估计得有几白万行代码呢,以至于他都无法迅速的定位需要修改的代码。
经过三天的紧张的工作,他最终顺利地完成了这个任务。
大家如果现在去访问,就可以看到他的杰作了!言归正传,我们这个题目的内容其实和小李的第一个任务差不多,不过我们的评判系统对于随机的东西不太在行,对于一串随机的字符串序列,它怎么会知道哪个是正确答案呢?于是我们把这件事情倒过来做,给出一个随机的字符串序列,要求同学们把这个序列按照字典顺序排列。
相信这么简单的任务你也可以解决!
Input
第一行是数字T,表示测试用例的数目1<=T<=10
每一组测试用例的格式如下:
第一行是数字n,代表字符串的个数1<=n<=100
接下来n行,每行包含一个字符串,注意我们的字符串将只由字母组成,不限大小写
字符串长度限定在30以内
Output
对于每组测试数据,第一行先输出测试数据的编号,从1开始
然后输出按字典顺序排好的字符串序列,每行一个
Sample Input
2
3
Y es
we
Can
3
cPP
JavA
c
Sample Output
1
Can
Y es
we
2
JavA
c
cPP
分析:囧题,看起来很吓人,就是一个字符串排序,注意输出要带序号,随便用什么排序法都行。