一、ACM竞赛介绍及规则$ x3 Y9 C* k) _7 U7 I* C; j
ACM/ICPC(国际大学生程序设计竞赛)是由ACM(Association for Computing Machinery,美国计算机协会)组织的年度性竞赛,始于1970年,是全球大学生计算机程序能力竞赛活动中最有影响的一项赛事。ACM/ICPC采用赛区选拔的方式产生参加世界决赛学校的资格, 2001年,来自全球超过25个地区1141所大学的2362支队伍参加了第26届ACM/ICPC的赛区竞赛。在2002年3月,来自世界各地的约60支队伍,200多名选手参加了夏威夷总决赛的角逐。可以说,ACM国际大学生程序设计竞赛是参赛选手展示计算机才华的广阔舞台,是著名大学计算机教育成果的直接体现,是信息企业与世界顶尖计算机人才对话的最好机会。在过去十几年中,世界著名信息企业APPLE、AT&T、MICROSOFT和IBM分别担任了竞赛的赞助商。中国大陆高校从1996年开始参加ACM/ICPC亚洲预赛,前五届ACM/ICPC亚洲区选拔赛在上海设有赛区,由上海大学主办。2002年,第六届ACM/ICPC亚洲预赛将该在北京设赛区,由清华大学主办。本次竞赛将于2002年10月在清华园拉开帷幕,预计将有超过60所国内外著名大学的上百支队伍参加本次竞赛(这也是北京工业大学首次参加此项赛事)。 9 x- p7 r2 }6 `$ w" l/ [& G1 \8 c# l% R$ p' F& G
ACM竞赛规定,教练是参赛队伍所代表学校的正式教师,每支队伍最多由三名参赛队员组成,每支队伍中至少有两名参赛队员必须是未取得学士学位或同等学历的学生,取得学士学位超过两年,或进行研究生学习超过两年的学生不符合参赛队员的资格,任何参加过两次决赛的学生不得参加地区预赛或者世界决赛。 / E5 r0 R) O& Y ~# n! H5 @) P e: T% |6 l R, M! Y
竞赛中至少命题6题,至多命题10题,比赛时间为5个小时,参赛队员可以携带诸如书、手册、程序清单等参考资料,试题的解答提交裁判称为运行,每一次运行会被判为正确或者错误,判决结果会及时通知参赛队伍,正确解答中等数量及中等数量以上试题的队伍会根据解题数目进行排名,解题数在中等数量以下的队伍会得到确认但不会进行排名,在决定获奖和参加世界决赛的队伍时,如果多支队伍解题数量相同,则根据总用时加上惩罚时间进行排名,总用时和惩罚时间由每道解答正确的试题的用时加上惩罚时间而成。每道试题用时将从竞赛开始到试题解答被判定为正确为止,期间每一次错误的运行将被加罚20分钟时间,未正确解答的试题不记时,地区预赛可以使用的语言包括C/C++和Java,每支队伍使用一台计算机,所有队伍使用计算机的规格配置完全相同。(竞赛具体的软件环境可能根据赞助商的变化而变)) g# Z( B) \* a4 b' `+ Z8 O
- f0 B& j/ e. g# N3 y+ d2 c/ S
二、关于竞赛的题型分析 % y8 E- o, G$ UHal Burch通过在1999年春季的分析得出了这样的结论,竞赛的程序设计一般只有16种类型,它们分别是: : c& X) a* Q) X 5 N5 q! b9 s3 z9 G' pDynamic Programming (动态规划) $ O" c$ M2 c, N5 o9 h4 gGreedy (贪心算法) " T0 l# g0 n3 i, I+ J. vComplete Search (穷举搜索) / H- R4 T, ?4 m8 p
Flood Fill (不知该如何翻译) ' s" a6 _4 l" g' f2 `8 X$ |Shortest Path (最短路径) 3 }* J, ]) s ~Recursive Search Techniques (回溯搜索技术) " ^1 ^1 I/ S* F8 E
Minimum Spanning Tree (最小生成树) 2 e+ |& b' ?+ k! R0 w$ N( h0 ]6 n V' K
Knapsack (背包问题) # P! Y, U- v g$ z
Computational Geometry (计算几何学) $ F0 w+ l2 ~3 N$ ~5 hNetwork Flow (网络流) $ k3 C3 q8 H) K% q. H( D) bEulerian Path (欧拉回路) " b4 e* J* Q. t
Two-Dimensional Convex Hull (凸包问题) + g' I0 ?4 L" [2 [+ A
BigNums (大数问题) e1 I$ c1 ~( m6 |0 Z
Heuristic Search (启发式搜索) - [- j( }- {; O$ e
Approximate Search (近似搜索) ' F/ y8 b) @! X [6 ^
Ad Hoc Problems (杂题)2 i: k" P7 b2 o% j5 d; X. k
/ p% j& W8 Y+ R8 ^
很少有人能真正掌握这其中绝大部分的方法,而对于一些包含了这些方法组合与循环的具有挑战性的综合问题,多数选手都无能为力,因为竞赛中的很多试题都需要选手当场作出分析,而不是套用固定的解题格式,这是竞赛的困难所在,也是它的魅力所在。 8 O4 i7 w, e @0 a; i; |& [( y; k2 g' b4 B0 I. R
三、竞赛准备 / ~9 c, }/ q: L( A4 z LACM竞赛不要求使用某一种特定的语言,所以各个队伍可以根据语言的特点和自己的特长选择,如果对语言的原理语法和特点均能做到成竹于胸、滥熟于心,在比赛的过程中就可以大大缩短调试的时间,从而获得优势。 : I+ E% j4 @* b0 ~9 e ; M) [" Q# ]' k& H, D) b; \4 q然而编程之道就如武学之道,语言只是各门各派的武功招式,算法和数据结构则好比内功心法和武学原理。内力深厚,任何招式到了手上都能够化腐朽为神奇;掌握了武学原理,更能做到无招胜有招。选手在竞赛中最重要的素质,正体现于对算法和数据结构的掌握和理解上,通过对经典问题的分析,掌握各种算法的应用范围和数据结构的作用与具体实现,是每个选手在平时学习中的重点所在。2 O# H& r: R0 M& H n! O; s; f
$ M J0 X; U1 r1 c9 W四、竞赛策略 ) F' i; h: t/ @1 a! O8 C临近比赛,在实力上已经难有质的提高,这时我们不妨将注意力转移到竞赛技巧方面,做不成武学道师也学个韦小宝。在ACM竞赛中,一般来说能成功解决半数或以上题目的队伍已经是相当优秀的,解决所有问题近乎天方夜潭,也就是说无论你的实力如何,都还有很大的改进余地,这其中比较重要的就是竞赛的策略。' o/ C$ o* O) G; G: |* x8 @ @
G2 ], r# e# }) x) p* C% }, j8 H
(1)分工的问题:! [+ W" `+ b% b6 ~
团队的配合十分重要,三个队员之间的合理分工可以大大改进解题的效率,根据队员的不同特点,不同的队伍可以采用不同的分配方式,其间一些细节的处理需要三个人有很好的默契。 3 B5 S# v7 j0 t7 S. m5 W 8 a8 b0 `. l, L" W! y2 g(2)算法的选择:6 I- g8 i8 d! c0 \/ f% u4 T
在所有可行的算法当中,我们选择的应该是最可行的方法,而不是最高明的方法,这是竞赛与解决问题的一个重要区别,按照熟悉的程度由高到低选择一个算法,通过计算算法的时间和空间复杂度(在必要的情况下)和特殊的测试数据找出一切使该算法不成立的理由,如果找不到就确定该算法并选用相应的数据结构。在确定思路的时候注意比较常见的思维方式分析,比如逆向的分析,对称的分析等等。 1 \# p/ E* K' f p4 O 1 k" y; {8 l' ^(3)程序的编写: " s, b4 _ ~6 y$ y! w' K最好首先编写输入和输出的部分,然后逐步细化,一个部分一个部分地填充调试,其间通过适量的注释来刻画程序的逻辑结构和特殊的技巧。在完成全部代码后用一般的测试数据验证代码的正确性,然后处理特殊的情况和边界问题,试图尽可能地找出错误的情况并加以改正。关于程序的优化主要考虑的是最坏情况下所用的时间是否满足要求,优化的程度以题目要求为准,足够即可,尽量避免使用指针和动态分配,在空间允许的情况下一律采用静态分配。% x8 L) _2 w$ [) v# @
5 W8 [/ q$ d e; G
(4)调试中的问题: ; u) D' H" ~9 o0 ?调试中会遇到的许多问题需要在事前有所准备并定出总体设计,当然具体的情况还要临场分析,考虑的方面包括程序中的BUG,算法的正确性和数据结构的合理性,什么时候该放弃这个问题,什么时候该返回到先前放弃的问题,是否需要做到或已经做到足够的优化等等。所有关于调试的输入输出都不要删除,将它们注释起来即可。/ g. [- r* x. ~5 x8 a7 b
9 \* v3 B. w. c ^! q C(5)竞赛中的杂题处理/ V! e- q: B. B5 X ?, Y- c2 y
在竞赛中有时会出现一些新颖的题型,解决它们的算法很难归到经典的算法中去,每个这类的题都有自己鲜明的特点,对于它们根本没有一般的解法。对于这样的挑战,一个新颖的数据结构或一套特殊的循环或判断常常是必须的。解决这种问题的关键在于仔细地阅读题目的叙述,灵感经常来自于将叙述的逻辑条理整理得十分清楚之后,同样,对这类题的优化也是需要的,至少需要避免过多的循环嵌套。( a1 ~! O; H/ \# C9 s" v8 |+ J