刺激与遗憾--记我的第一场ACM/ICPC比赛
关于这次比赛,它和正规的ACM/ICPC不同,不是三人组队,而是一人一机,时间也缩短为3小时,八道题目。而且题目居然全部翻译成了汉语,这个搞不懂组织者是怎么想的。不过它好歹也算我生平的第一场ACM比赛吧。
这一段时间由于太忙,高数,大物两座大山压得喘不过气,还有抽出大部分时间研究C游戏的代码。所以也没怎么准备,就在PKUOJ上做了几道题找找感觉,昨晚上的时候把有点用的书都整理好,看了看一些最基本的算法。我想,反正现在数据结构也没看多少,比赛时遇到什么最短路径模式匹配什么的就PASS,把那些对算法要求不是很高的努力攻攻,这样应该比较适合我;再说了,反正现在自己才大一,和高年级的比肯定在知识上有差距,但对ACM的熟悉程度肯定比不少人好,这次能怎样就怎样,就当垫个底,反正以后大二大三还有机会。
本来今天该去新校区做物理试验的,翘了,托LL帮我搞定。早上其他人坐上校车风风火火向秦岭迈进时,我和另两个同学坐上二十九路向北边的本部驶去。其中一人就是上文提到的W同学,另一人是Z同学,04年接触的ACM,比较强。本来还有J同学的,编程方面的大牛,因为担心翘实验课挂掉,就放弃了这边的比赛。
比赛九点开始,我们提前半小时上了位于毅字楼四楼赛场,哪里的机器确实不敢恭维,从启动速度就可以推断出其配置水平。用的还是WIN2000,不过也许是从安全性方面考虑的吧。待把一切都调试好后,时间还早,就静静的坐在那里,看屏幕上的时刻一秒一秒的流逝。
在9:00三小时倒计时开始的同时,我摁下“刷新”,八道题目中首先被第一道标题所吸引:一道简单的运算。点开看完题目,知道这是给人找自信和避免零纪录的,于是打开VC,写下12行代码,提交。Accept!果然,我自认为做的比较快了,但也只能排在十名左右。开始第二道题,剩余的题目都差不多,一道道点开,初略的看了看,看到E题时,是一道关于冥指数的,一个激灵,想起好像以前这题在北大OJ上做过,而且算法还能记得。稍微整理了一下思路,就开始写,写完后带入示例数据测试,没出错,马上提交,果然,又是一个鲜红的Accept。我看了下排行榜,目前只有我一个人做出两道题,排第一。而此时时间才过了十几分钟。
紧接着点开F题,是砍木桩的(题目见末尾)。初看觉得很麻烦,输出还要按序输出。仔细一想,似乎有点思路,管他的,边想边写。写着写着发现就是设数组,用个循环依次比大小,一直到当前位比后一位小时就输出当前位。写好后带入数据测试,不符,冥思半天后发现忘了倒下的木桩还要压到后面的木桩。然后又改,又是编译、测试的循环。其中有几次和范例结果一致了提交,但总是返回WrongAnswer!最后一次把代码从头到尾看了一遍,觉得应该没错了,提交,依然未过。由于数组的下标是从0开始的,也就是说第1个数据在数组中的标号是0。一直错下来,我早已被这个搞晕了,越看“i”,“i-1”一类的东西越混淆。索性把a[0]设为0,从下标为1开始计算,这样比较符合日常思维。可修改了N次,测试数据的那个“9125433662”我都熟读成诵了,还是过不了。
看看时间,我已在这道题上耗了差不多一小时,过的题目依然是2道。现在看排名上已经有多人过了3道。我决定马上放弃这个讨厌的“木桩”。看了看排名榜,基本上前面的都过了C题。那么C题应该不难。点开一看,是个数据校验的题,确实很简单,至少我没怎么想就开始写代码了。依然是编译,测试,符合示例结果。然后提交,不出所料又一次通过。
接下来做H题,标题是“SurprisingString”,那么和字符串有关。要求是先给出SurprisingString的定义,然后求任意输入一个五位的字符串,判断他是不是SurprisingString。当时我就看出,这题要正规的做出来,至少于我,是比较麻烦的。而且当时因为很心疼F题浪费的大块时间,思维很难集中。但是,因为字符串只有五位,完全可以用穷举法搞定,而且绝对不会错,唯一的缺点就是需要敲的代码多了点。花了较长的一段时间写完后,提交,又是一次通过!
看看排行榜,我排第6,在过4道题的人中,罚时很少。现在离结束还有四时分钟,先点开一道关于等差数列和双平方数集合的题,想了一会决定用暴力破解法来做,第一次带入测试数据后发现结果差得很远,马上放弃。然后点开一道标题为“ACM分组”的题,看了看,算法不难,只是涉及字符串排序外加未知数N的K约数,嫌麻烦,担心时间不够,又扔掉,并决定把剩下的半小时全拿来攻那道“木桩”题。
最后的近半小时依然诡异,改了无数次就是过不了,最后了,我在一次随机输入中得到了一组特殊的测试数据:6124325。即一根木桩比他前一根高,而且它又是最后一根的情况。马上在最后一行代码中加上一条if+printf语句,解决了这种特例。看看倒计时,还剩最后16秒钟,我立刻提交,期望在最后时刻来一个“压哨球”,然而返回的依然是WrongAnswer。
最终的排名出来了,加上那个未报名的Xiaolan,我排第13(063413那个,即我的学号,06代表06级),因罚时少(240)排过四道的人中的第2。最多的过了5道,看了看第一名的罚时,296,崩溃了!要是我最后时刻的那次提交过了的话,我就会因罚时的优势排到第一!太遗憾了!而Z同学的运气就好了许多,因最后2秒的一次Accept,他过了5道,排到了11。还算意料之中。
下面公布那道让我崩溃的题及我的代码,如果哪位看客能指出我的错误或给出些BT的测试数据的话,我将不胜感激!不然死不瞑目啊!
描述:
为了使奶牛能够吃的更多的青草,农夫发现他必须将农场上的N(1<=N<=50,000)各木桩移除。为了简单期间,假设这N个木桩被排成一排,并且从1到N标号,每个木桩的高度为Hi(1<=Hi<=10,000).农夫采用了一种传统的移除方法来移除所有的木桩。这个方法就是当移除一个木桩后,它会将与它相邻的并且高度比它矮(不包括相等)的木桩压倒。例如有如下一排木桩,高度如下:1 2 5 4 3 3 6 6 2如果农夫砍倒第三个木桩(高度为5),然后第一个和第二个会被压倒,同时第四个和第五个木桩也会被压倒,也就是说砍倒第三个木桩后这一排木桩的状态如下:* * * * * 3 6 6 2其中*表示已经不存在了,然后再砍倒第七个和第八个木桩就可以将所有木桩移除。请帮助农夫计算对于一排木桩,他至少要砍倒那几个木桩才能将所有木桩移除,输出要砍倒的木桩。
输入:
第一行:一个整数N第二行到第N+1行:第i行的整数表示第i个木桩的高度
输出:
每行一个整数,表示要砍倒的木桩编号,要求输出的编号是递增序的。
输入样例:
9
1
2
5
4
3
3
6
6
2
输出样例:
3
7
8
我的代码:
#include
void main()
{
longi,j,n,t;
int x,mu[50001];
mu[0]=0;
scanf(“%ld”,&n);
for(i=1;i<=n;i++)
scanf(“%d”,&mu[i]);
for(i=1;i
if(mu[i+1]<=mu[i])
{ x=mu[i];
printf(“%ldn”,i);
for(j=i+1;j<=n;j++)
{ t=j;
if(x<=mu[j])
{
i=t-1;
break;
}
}
}
if(mu[n]>mu[n-1])printf(“%ld”,n);
}
——————————————————————————————
复制完代码我发现,难道最后一行该是mu[n]>=mu[n-1]?我跳楼去了!!
5.29补:现在看出来,这道题不是那么简单,代码有很多漏洞.另换了一种算法.