ACRush 楼天城回忆录
利用假期空閑之時(shí),將這幾年 GCJ , ACM , TopCoder 參加的一些重要比賽作個(gè)回顧。首先是 GCJ2006 的回憶。
Google Code Jam 2006
一波三折:
Google Code Jam 2006 是我第一次到美國(guó)參加現(xiàn)場(chǎng)的程序設(shè)計(jì)比賽。 Google Code Jam 2006 的比賽地點(diǎn)設(shè)在了紐約,這次紐約之行之前的簽證出了不小的問(wèn)題,這里非常感謝大家對(duì)我們的關(guān)心,特別感謝吳總( wyy )和魯小石的幫助,使我最終踏上紐約之旅。
從北京到紐約的飛行時(shí)間是 13 個(gè)半小時(shí),由于是第一次做超過(guò) 8 小時(shí)的飛機(jī),沒(méi)有什么必要的經(jīng)驗(yàn)和準(zhǔn)備,路途非常疲勞。一到賓館就睡了,結(jié)果由于手機(jī)鈴聲的時(shí)間使用的是東方時(shí)間,差了 12 個(gè)小時(shí),一覺(jué)把所有事情連晚飯一起都睡過(guò)了,隨便吃點(diǎn)東西就繼續(xù)睡了。之后的所有現(xiàn)場(chǎng)比賽我都養(yǎng)成了提前睡覺(jué)的習(xí)慣,以保證充足的體力。
比賽過(guò)程:
比賽時(shí)精神狀態(tài)還算可以,但是分配了比賽房間之后發(fā)現(xiàn)自己和 tomek 分在一個(gè)房間,真是很不爽;在和旁邊的 zhuzeyuan 抱怨的時(shí)候,發(fā)現(xiàn)他和 Petr 一個(gè)房間,彼此彼此吧。
下面就是比賽過(guò)程了,總體來(lái)說(shuō)比賽過(guò)程比想象的艱苦,不過(guò)其實(shí)在 System Test 之前的結(jié)果還是很滿(mǎn)意的,先簡(jiǎn)單描述一下 3 道題目吧。
250 分的題目是一道平面極值問(wèn)題,給定 n 個(gè)點(diǎn),求一條直線,使得 n 個(gè)點(diǎn)到這條直線的 y 方向截距總和最小。我回憶起金凱在 2003 年集訓(xùn)隊(duì)論文中報(bào)告中講到的很類(lèi)似的一道題目,記得一個(gè)重要結(jié)論是這條直線一定經(jīng)過(guò)兩個(gè)點(diǎn),雖然題目有些不同,但是很快得到了相同的重要性質(zhì):這條直線一定經(jīng)過(guò)兩個(gè)點(diǎn)。這樣很容易得到一個(gè) O(n3) 的算法。
500 分的題目是一道反 Hash 函數(shù)問(wèn)題,給定一個(gè) Hash 函數(shù)和 x ,求一個(gè)最小的非負(fù)數(shù) y 使得 H=x 。估計(jì)了一下,單向搜索需要 26^8 ,于是我改用雙向搜索,這樣就變成了 26^4 。但是實(shí)現(xiàn)過(guò)程比想象的復(fù)雜很多,提交了后只有 280 左右了。其實(shí),這題有更簡(jiǎn)單的數(shù)學(xué)方法, tomek 的程序有 450+ 。
1000 分的題目是涉及卷積函數(shù)和計(jì)算反函數(shù)的問(wèn)題,通過(guò)轉(zhuǎn)化變成線性方程求解問(wèn)題。當(dāng)時(shí)受到現(xiàn)場(chǎng)氣氛的影響有些緊張,浪費(fèi)了不少時(shí)間,提交之后 550 分左右。其實(shí),當(dāng)時(shí)一些原理問(wèn)題都沒(méi)有想清楚,不過(guò)后來(lái)和 Ying (王穎)經(jīng)過(guò)討論驗(yàn)證都是正確的。
Coding 結(jié)束之前 Petr , tomek , Ying 和 andrewzta 都提交了 3 題,其中 Petr 領(lǐng)先得比較多,我和其余 3 人差距 50 分以?xún)?nèi)。
Challenge 階段開(kāi)始之后,我由于 500 分題自己使用的是雙向搜索的算法,沒(méi)有注意到有些單向的搜索加模線性方程的方法其實(shí)是正確,在 10 分鐘以?xún)?nèi) cha 錯(cuò)了 2 次。落后于上述的 4 個(gè)人,排在第五。
但是下面的 5 分鐘發(fā)生了戲劇性的一幕,首先是 Petr 的 250 被 cha 了,接著 Ying 的 250 也被 cha 了,這樣我面臨這樣一個(gè)情況: tomek 領(lǐng)先我 100+ 分, andrewzta 領(lǐng)先我 30+ 分,由于我和 tomek 處在一個(gè)房間,所以我做出了一個(gè)大膽的決定,就是 challenge tomek 的 1000 分題,我隨機(jī)生成了一個(gè)隨機(jī)大數(shù)據(jù),在最后時(shí)刻提交了這個(gè) challenge ,系統(tǒng)返回了一個(gè)令人窒息的結(jié)果: successfully challenge 。憑借這 50 分我一舉超過(guò)了 tomek 和 andrewzta ,在 System Test 之前占據(jù)了榜首的位置。
戲劇性的結(jié)果:
我很有幸能夠在第一次參加現(xiàn)場(chǎng)比賽時(shí),就能夠和冠軍這么接近,如果 System Test 能夠全部 Pass 的話(huà),這可以認(rèn)為是一場(chǎng)完美的比賽。
可是,整個(gè)故事就好像是被刻意設(shè)計(jì)的一樣, System Test 之后的結(jié)果使我目瞪口呆:首先是 250 分的題目,我由于有一個(gè)地方?jīng)]有及時(shí)使用 double ,而造成整數(shù)越界;然后, 1000 分的題目簡(jiǎn)直是悲劇的最高境界,我在高斯消元的時(shí)候沒(méi)有及時(shí)把一個(gè)重要變量暫存,導(dǎo)致影響了結(jié)果,沒(méi)有想到竟然躲過(guò)了那么多大數(shù)據(jù),但是不能通過(guò) System Test 。最后排在 50 名左右。這兩個(gè)錯(cuò)誤至今刻骨銘心。
最終 Petr 獲得冠軍, Ying 亞軍, andrewzta 由于 500 掛了排在第 3 。
11 月的紐約有些冷,我隨大隊(duì)人馬一同去了一趟帝國(guó)大廈,景色很迷人。第二天休息一下后與幾個(gè)中國(guó)選手打了一會(huì) “ 找朋友 ” ,第一次美國(guó)之行就結(jié)束了。
總結(jié):
比賽結(jié)果雖然不是很理想,但是對(duì)于第一次參加世界比賽的我還算可以接受。也算是為今后的比賽留下一些教訓(xùn)吧。
在帝國(guó)大廈上見(jiàn)識(shí)了大家的拍攝功底,我由于技術(shù)差沒(méi)有拍到任何合適的照片。
在比賽過(guò)程中,首次見(jiàn)識(shí)了 liympanda 的大將風(fēng)度,和 panda 在一起總是笑口常開(kāi),他無(wú)論遇到什么情況都無(wú)所畏懼,這一點(diǎn)我一直在努力學(xué)習(xí),不過(guò)一直做的不好。但是 panda 打牌的時(shí)候就不一樣了,總是喜歡偷看別人的牌,還炫耀自己會(huì)說(shuō)廣東話(huà),被 Ying 和 rocking 兩位廣東選手狠狠鄙視了一番。
Petr 加上之前的 TCO 和之后的 TCCC ,拿到了 2006 年的大滿(mǎn)貫,可以算是歷史性的突破吧。 Tomek 有些可惜,比完了還問(wèn)我怎么 cha 他 1000 分的,呵呵。
其實(shí)這次比賽 Ying 挺可惜的,其實(shí) Petr 的發(fā)揮并不很好,如果 Ying 運(yùn)氣再好一些的話(huà),歷史從那時(shí)就要重寫(xiě)了。不過(guò) Ying 還是體現(xiàn)了他超強(qiáng)的數(shù)學(xué)功底,讓人佩服。另外,來(lái)自復(fù)旦的同省隊(duì)友 LemonTree 也獲得了好成績(jī)。
這好像是自己最后一次和 xreborner 同場(chǎng)競(jìng)技了(由于之后 xreborner 退役了很長(zhǎng)時(shí)間,忘記 GCJ2008 我們又見(jiàn)面了,謝謝 Savior 的提醒),感謝您在我高中時(shí)期教授了我許多編程技巧,我一直沿用至今。
利用假期空閑之時(shí),將這幾年 GCJ , ACM , TopCoder 參加的一些重要比賽作個(gè)回顧。昨天是 GCJ2006 的回憶,今天時(shí)間上更早一些吧,我現(xiàn)在還清晰記得 3 年前,我剛剛參加 ACM 時(shí)參加北京賽區(qū) 2005 和杭州賽區(qū) 2005 的情況。
2005 年 ACM-ICPC —— 酸甜苦辣
我進(jìn)入清華大學(xué)開(kāi)始本科學(xué)習(xí)的時(shí)間是 2004 年 8 月,在進(jìn)入清華大學(xué)的第一年里,由于基礎(chǔ)課學(xué)習(xí)比較緊張,再加上計(jì)算機(jī)系不允許大一學(xué)生自帶電腦,我沒(méi)有參加 2004 年的 ACM 比賽。不過(guò)在大一一年中沒(méi)有停止這方面的練習(xí),對(duì) ACM 還是熱情高漲。
大概在 2005 年 7 月底,與同班同學(xué) shell (貝小輝)和 superzn (張寧)一起決定組隊(duì)參加 ACM 比賽。對(duì)于隊(duì)名沒(méi)有太多的想法,就隨便取了一個(gè)字典序靠前一點(diǎn)的 bomber 。隨后進(jìn)行的幾場(chǎng)訓(xùn)練中,我的編程狀態(tài)一直保持得很好,訓(xùn)練比賽的主要方式都是:我主寫(xiě)程序, shell 和 superzn 負(fù)責(zé)翻譯題目,思考算法和測(cè)試。這種組隊(duì)模式一直沿用到我們后面的所有比賽中。
2005 年底,我們報(bào)名參加了 2005 年的北京賽區(qū)和杭州賽區(qū)的比賽。順利通過(guò)了預(yù)賽進(jìn)入了現(xiàn)場(chǎng)決賽。記得當(dāng)時(shí)北京賽區(qū)預(yù)賽的時(shí)候,我和 superzn 一起在參加百度之星程序設(shè)計(jì)大賽, shell 依靠一人之力過(guò)了 6 題,最后以第二名的資格參加北京賽區(qū)現(xiàn)場(chǎng)比賽。
北京賽區(qū):
2005 年的北京賽區(qū)地點(diǎn)設(shè)在隔壁的北京大學(xué),由于交通非常方便,我們沒(méi)有和大部分選手住在一起,不過(guò)也沒(méi)有參加 Java-Challenge 和晚上的表演。
練習(xí)賽之前,說(shuō)到比賽位置抽簽,本身意義不是很大,可是鄔老師神奇的 RP 把兩只清華的隊(duì)伍抽在一起,結(jié)果練習(xí)賽進(jìn)行了一半,另一只清華的隊(duì)伍 THU1 (隊(duì)員是:吳景岳,栗師和金凱,好像后來(lái)隊(duì)名改成了 DreamCatcher ,不是很確定)被要求換到一個(gè)比較遠(yuǎn)的地方,理由是有些學(xué)校覺(jué)得這樣不合理。后來(lái)很多賽區(qū)也出現(xiàn)過(guò)隊(duì)伍座位在一起的情況,鄔老師的 RP 果然不是蓋的。
記得練習(xí)賽時(shí)和復(fù)旦的 LemonTree (盛城)一起在場(chǎng)地里閑逛,結(jié)果果然不到 10 分鐘就被要求回座位了。還有當(dāng)時(shí)比賽場(chǎng)地是一個(gè)體育館,有些隊(duì)伍把氣球放飛之后氣球就飄在天花板下了,總裁判李文新老師還威脅我們說(shuō),如果明天正式比賽把氣球放飛,就不算通過(guò)相應(yīng)的題目,除非有辦法把氣球取下來(lái)。
然后就是比賽的過(guò)程了,下面有底紋的文字是我找到的當(dāng)時(shí)留下的比賽總結(jié):
E :快速排序。 5 分鐘 1Y 。
我想 5 分鐘的時(shí)間可以爭(zhēng)取這幾年 ACM 國(guó)內(nèi)賽區(qū)的最快出題記錄了吧。
G :二分答案 + 最小生成樹(shù)。 25 分鐘 1Y 。
這題就是經(jīng)典的最優(yōu)比例生成樹(shù)問(wèn)題,我們一致認(rèn)為這題比較簡(jiǎn)單。不過(guò)后來(lái)被李文新老師批評(píng)了,說(shuō)法是誤導(dǎo)其他的隊(duì)伍。不過(guò)說(shuō)到最優(yōu)比例生成樹(shù)問(wèn)題, TCO2006 的時(shí)候 fwj 和 tomek 竟然都沒(méi)有見(jiàn)過(guò)這道題目,這題可是源于 POI 呀。我想我們認(rèn)為這道題目簡(jiǎn)單的主要原因是我們都在冬令營(yíng)上見(jiàn)過(guò)這到題目,如果第一次看見(jiàn),想出算法可能確實(shí)需要一些時(shí)間。在這里向被我們影響的隊(duì)伍的道歉,最終 G 提交了 200 多次,但是只有 8 個(gè)隊(duì)伍 AC 。
C :二分圖最大匹配。 42 分鐘 1Y
題目要求計(jì)算一張圖的最小覆蓋集,可能唯一的 tricky 是發(fā)現(xiàn)圖是二分圖。
D :遇到了一定的困難,發(fā)現(xiàn) A 很簡(jiǎn)單,于是先放一下
D 是一道比較綜合的題目,設(shè)計(jì)一些簡(jiǎn)單的計(jì)算幾何和字符串處理的知識(shí)。
A :簡(jiǎn)單的幾何問(wèn)題,出現(xiàn)了一個(gè)低級(jí)錯(cuò)誤,提交了 3 次均為 WA 。
A 是北京賽區(qū)最簡(jiǎn)單的題目,我的程序里犯了一個(gè)很低級(jí)的錯(cuò)誤,可能也是經(jīng)驗(yàn)不足造成的吧。
D :重新寫(xiě),但是沒(méi)有考慮一種情況, WA 了 1 次。
87 分鐘,復(fù)旦的 Abuacus 過(guò)了 4 題占據(jù)了 Rank1 。由于隊(duì)伍模式的原因,我們?cè)谶€有很多簡(jiǎn)單題目的情況下卡住了長(zhǎng)達(dá) 30 分鐘。
A : shell 突然發(fā)現(xiàn)了 A 程序中的低級(jí)錯(cuò)誤, 105 分鐘 AC ,重新奪回 Rank1 。
這是很重要的一步,現(xiàn)在想來(lái)如果沒(méi)有這個(gè)發(fā)現(xiàn),后果可能不堪設(shè)想。
B :二分答案 +2SAT 。 129 分鐘 AC 。
B 是一道明顯的 2SAT 問(wèn)題,由于題目比較長(zhǎng),我們沒(méi)有很早發(fā)現(xiàn)這道簡(jiǎn)單題。
D :發(fā)現(xiàn)了 D 的沒(méi)有考慮的情況, 140 分鐘 AC 。
看了一個(gè) board ,那時(shí) Abuacus , Eccentric 都只有 4 題,能夠在第一次參加正式比賽就做到 6-4 的領(lǐng)先,當(dāng)時(shí)心情很激動(dòng),不過(guò)由于缺少經(jīng)驗(yàn),也影響了接下來(lái)的發(fā)揮。其實(shí),現(xiàn)在回想起來(lái),這次比賽其實(shí)是一個(gè)很好的 AK 的機(jī)會(huì)。
F : DP 。程序比較復(fù)雜, WA 了 4 次。
F 是一道比較復(fù)雜的動(dòng)態(tài)規(guī)劃的題目,其實(shí) WA 的原因是一個(gè)應(yīng)該用 int64 的地方,我們使用了 int ,這個(gè)地方的確很難發(fā)現(xiàn)。
H : F 一時(shí)無(wú)法 AC ,只好轉(zhuǎn)功 H 。 H 就是普通的模擬題。開(kāi)始沒(méi)有考慮坦克和炮彈可能在 1/3 秒相遇, WA 了 1 次。
比賽還有一個(gè)小時(shí),封板。
H : shell 發(fā)現(xiàn)了坦克和炮彈可能在 1/3 秒相遇的情況, 250 分鐘左右 AC 。
對(duì)于我們這種組隊(duì)模式,當(dāng)主寫(xiě)程序的選手狀態(tài)不好的時(shí)候,很容易出現(xiàn)連續(xù)卡題的情況,這種情況的出現(xiàn)很不利于水平的正常發(fā)揮。在北京賽區(qū)的比賽中,我們很有幸沒(méi)有出現(xiàn)連續(xù)卡處的情況。
記得,當(dāng)時(shí)北京賽區(qū)的 Judge 的半自動(dòng)的,就是說(shuō)如果結(jié)果是 AC ,速度就會(huì)非常快,否則由于人的介入,不能 AC 的提交往往需要等一段時(shí)間。我們第 2 次提交 H 之后,沒(méi)有得到很快的回復(fù),以為已經(jīng) WA 了,于是我和 superzn 繼續(xù)測(cè)試一些數(shù)據(jù)。但此時(shí),突然有一個(gè) mm 從左邊走過(guò)來(lái)插氣球,這個(gè)氣球也成為了全場(chǎng)唯一的藍(lán)色氣球,這個(gè)意外之喜最后成就了第一個(gè)分區(qū)賽冠軍。
F :下面就是痛苦地提交 F ,一直戰(zhàn)斗到最后一刻, WA 了 14 次,留下了北京賽區(qū)最大的遺憾。
在最后時(shí)刻我們似乎發(fā)現(xiàn)了那個(gè) int64 的錯(cuò)誤,不過(guò)當(dāng)時(shí)思路已經(jīng)比較混亂了,沒(méi)能改對(duì)。 F 的問(wèn)題也導(dǎo)致沒(méi)有時(shí)間寫(xiě) I ,當(dāng)時(shí)如果直接重寫(xiě)后者換 superzn 來(lái)寫(xiě) F ,完全可以在比賽結(jié)束前 AC 。
比賽的大致過(guò)程如上所述,那個(gè)神奇的氣球,我現(xiàn)在仍然記憶猶新。最終有 4 個(gè)隊(duì)伍攻破 7 題, Abacus 的組成應(yīng)該是盛城, timegreen 和 suzhan 吧, Eccentric 中我只記得辛韜, ZSU_Panku 中我記得 Savior (陳實(shí))。上述的老朋友之后見(jiàn)面的機(jī)會(huì)就很少了,分區(qū)比賽也成為了我好需要老同學(xué)重要的交流機(jī)會(huì)了。
我 ACRush 的 ID 估計(jì)就是那時(shí)開(kāi)始使用的吧,轉(zhuǎn)眼就已經(jīng) 3 年多了。
比賽前后還記得經(jīng)常與復(fù)旦大學(xué)的吳永輝老師聊天,在那之后的每次比賽我都能見(jiàn)到他年輕的身影。
現(xiàn)在回想起北京的分區(qū)賽,很有幸能夠在第一次參加 ACM 正式比賽就獲得分區(qū)比賽的冠軍。我想是由于現(xiàn)場(chǎng)氣氛對(duì)許多隊(duì)伍都有不小的影響吧,當(dāng)時(shí)許多隊(duì)伍都卡在幾道比較繁瑣的題目上了,題目的算法性都不是很強(qiáng)。我大概從那時(shí)才剛剛接觸 TopCoder ,如果能夠早一些,相信會(huì)更適應(yīng)這樣的比賽。
杭州賽區(qū):
2005 年的 ACM 杭州賽區(qū)比賽在浙江大學(xué)舉行,杭州賽區(qū)的時(shí)間就在北京賽區(qū)結(jié)束后一周,最初選擇杭州賽區(qū)的原因很飄逸:我自己家在杭州。實(shí)際上也差不多,我隨隊(duì)伍(當(dāng)時(shí) THU 派了 3 只隊(duì)伍參加杭州賽區(qū)的比賽,除了我們隊(duì)之外, b142857 (侯啟明), zhy (周源), ysy (楊思雨)組隊(duì),另外一只由汪汀,王俊和黃源河組成)一同抵達(dá)杭州車(chē)站之后就馬上回家休息了,直到比賽前才趕回。在北京到杭州賽區(qū)之間的一周中,我的狀態(tài)就在不斷下滑,在家中完全失去了比賽的氣氛,回到賽場(chǎng)再也找不到感覺(jué)了。一場(chǎng)悲劇即將上演。我們先看看比賽過(guò)程吧,下面有底紋的文字是我找到的當(dāng)時(shí)留下的比賽總結(jié):
G :初看很簡(jiǎn)單,但是調(diào)試了 30 分鐘沒(méi)有結(jié)果。
G 是一道數(shù)學(xué)問(wèn)題,其實(shí)《具體數(shù)學(xué)》書(shū)上有明確的公式,不過(guò)我們使用的遞推方法應(yīng)該也可以得到正確的結(jié)果。程序中犯了一些低級(jí)的錯(cuò)誤,由于實(shí)在不在狀態(tài),調(diào)試了 30 分鐘還沒(méi)有找到錯(cuò)誤。這里還暴露了一個(gè)組隊(duì)模式的問(wèn)題,在后來(lái)的組隊(duì)模式中,如果像這樣沒(méi)有想清楚算法的題目隊(duì)友是一定不允許我去寫(xiě)的。
A :模擬。 41 分鐘 AC ,當(dāng)時(shí)肯定沒(méi)有想到這是唯一一道 1Y 的題目。
A 是一道模擬題, 1Y 的時(shí)候已經(jīng)很晚了,排名也很靠后。
C :圖論。但是由于堆棧逸出 RTE 了 5 次,浪費(fèi)了大量的時(shí)間。
C 的問(wèn)題關(guān)于樹(shù)中祖先關(guān)心的判定,題目很簡(jiǎn)單,實(shí)現(xiàn)的方法也很容易,就是通過(guò)一遍 DFS 來(lái)計(jì)算。但是我們忽視了一個(gè)從來(lái)沒(méi)有遇到過(guò)的問(wèn)題:堆棧溢出。而且,堆棧在本地機(jī)器上運(yùn)行過(guò)程中, Eclipse 提供了 8MB 左右的堆棧,所以沒(méi)有溢出,但是在提交之后的環(huán)境下運(yùn)行就溢出了。而且每次 RTE 之后,我們一直在嘗試修改數(shù)組的大小,一直沒(méi)有找到根本原因。調(diào)試 C 的同時(shí),我也嘗試修改 G ,結(jié)果 G 也錯(cuò)了 8 次之多,并且始終都是 WA 。
I : shell 在我郁悶地調(diào)試 C 和 G 中 AC 了,之前 WA 了一次。
I 是動(dòng)態(tài)規(guī)劃問(wèn)題, WA 一次可能是忽視了一些邊界情況。
D :網(wǎng)絡(luò)流,沒(méi)有想到先貪心進(jìn)行優(yōu)化。 TLE 了 5 次最終沒(méi)有通過(guò)。
D 就是計(jì)算最小割,我們事先準(zhǔn)備了先流推進(jìn)算法,不過(guò)根據(jù)這道題目的模型,先流推進(jìn)算法遇到最壞情況:二分圖。由于當(dāng)時(shí) dinic 還不是很流行,我們 TLE 了 5 次還沒(méi)有通過(guò)。
郁悶地調(diào)試 D 和 G 。
E,B :都嘗試過(guò),但是都出現(xiàn)了不明的問(wèn)題。
在隨后的時(shí)間里,不斷調(diào)試 D 和 G ,但是始終不能 AC 。之后又嘗試 E 和 B , E 通過(guò)分段的方法可以處理, B 是數(shù)學(xué)題目。正常的話(huà) E 和 B 并不是很困難的題目,但是當(dāng)時(shí)已經(jīng)非常混亂,連樣例都沒(méi)有通過(guò)。
最終我們只過(guò)了 3 題,排在 21 名,經(jīng)歷了我參加 ACM 以來(lái)最慘痛的失敗。這次失敗主要?dú)w過(guò)與我狀態(tài)太差,基本上什么題目都不能順利通過(guò)。當(dāng)然題目的選擇也有很大的問(wèn)題: G 確實(shí)不是難題,但是由于未知的原因始終不能通過(guò),后來(lái)我把紙上的程序敲在 ZJU 上就 AC 了,至于現(xiàn)場(chǎng)為什么不能 AC 我現(xiàn)在還是不能明白。如果說(shuō)第一題的選擇直接影響了我們的信心,那么 D 的堆棧溢出則完全打亂了我們的節(jié)奏。對(duì)于我們的組隊(duì)模式,卡出 2 題已經(jīng)超出了極限,我們不可能再?lài)L試其他題目。
Abacus 也來(lái)到了杭州,他們前期體現(xiàn)了強(qiáng)勁的先期優(yōu)勢(shì),在 2 小時(shí)就達(dá)到了 6 題; b142857 (侯啟明), zhy (周源), ysy (楊思雨)的隊(duì)伍表現(xiàn)得相當(dāng)神勇,在最后一小時(shí)超越了 Abacus ,奪得了冠軍。
杭州賽區(qū)的失敗至今仍是心中痛苦的回憶,不過(guò)這個(gè)教訓(xùn)也是對(duì)我今后的學(xué)習(xí)生活的一種警示。
總結(jié):
2005 年是我第一年參加 ACM-ICPC 的比賽,兩場(chǎng) ACM 分區(qū)賽,我們經(jīng)歷了奪冠的興奮,也經(jīng)歷了環(huán)顧四周等待比賽結(jié)束的無(wú)奈。 2004 年清華沒(méi)有獲得任何分區(qū)賽的冠軍, 2005 年清華打了個(gè)漂亮的翻身仗,先后在成都,北京和杭州奪得冠軍,而且是三支不同的隊(duì)伍。
兩個(gè)賽區(qū)的 G 都是有傳奇色彩的題目。北京賽區(qū)中,我們 25 分鐘 1Y 了 G ,導(dǎo)致許多隊(duì)伍跟風(fēng)失敗,最終達(dá)到了 208 提交 8AC 的低通過(guò)率。但是,杭州賽區(qū)中, G 從比賽一開(kāi)始就占用了我們大量的時(shí)間,直到最后都沒(méi)有通過(guò),估計(jì)至少浪費(fèi)了兩個(gè)小時(shí)左右。真所謂成也在 G ,敗也在 G 。
北京賽區(qū)后, POJ 的論壇上傳聞?wù)f我曾經(jīng)說(shuō)過(guò) “ 起身去廁所,不許碰鍵盤(pán)。。。 ” ,很敬仰那些同學(xué)搞笑和扯淡的功底,我們雖然定下了以我主寫(xiě)程序的組隊(duì)模式,但是也非常重視配合和每個(gè)人在隊(duì)伍中的重要作用。
當(dāng)時(shí)清華沒(méi)有組織校內(nèi) PK 選拔,選擇了成都賽區(qū)的冠軍隊(duì) THU1 參加全球總決賽,當(dāng)時(shí)總決賽隊(duì)伍是以參考第二賽區(qū)的成績(jī)決定的,現(xiàn)在回想起來(lái)也是很合理的。由于最終我們未能得到機(jī)會(huì)參加全球總決賽,接下來(lái)幾個(gè)月我們情緒低落, bomber 從那時(shí)也就宣布解散了吧。
2005 年的比賽過(guò)程中,我見(jiàn)到了許許多多的老朋友。用吳永輝老師的話(huà), ACM 競(jìng)賽可以看作一些老朋友一起進(jìn)行的一場(chǎng)智力游戲。
利用假期空閑之時(shí),將這幾年 GCJ , ACM , TopCoder 參加的一些重要比賽作個(gè)回顧。回顧了 GCJ2006 和 2005 年的 ACM 之后,轉(zhuǎn)向 TopCoder 的比賽吧。我參加的最早的 TopCoder 賽事是 TCCC2006 。
TCCC2006 —— 死亡之組
TopCoder Collegiate Challenge( 簡(jiǎn)稱(chēng) TCCC) 是 TopCoder 一般在秋季舉行的面向全世界在校學(xué)生的程序設(shè)計(jì)大賽, 2006 年的 TCCC 在圣地亞哥舉行。從北京到舊金山的飛行只需要 11 個(gè)小時(shí)左右,所以不至于那么疲勞。路上一切都很順利,很感謝 OpenGL 的提醒,對(duì)于超過(guò) 8 個(gè)小時(shí)飛行自帶拖鞋和枕頭對(duì)我來(lái)說(shuō)還是很重要的。
TCCC2006 使用的標(biāo)準(zhǔn)的 TopCoder 現(xiàn)場(chǎng)比賽形式,比賽有 48 名選手參加,首先 48 名選手被分為 16 個(gè)人一組,每組分別進(jìn)行半決賽,前 2 名直接晉級(jí)決賽, 3-6 名晉級(jí) wildcard 比賽, wildcard 比賽 12 人中的前兩名填補(bǔ)決賽的最后 2 個(gè)名額,決賽由 8 個(gè)選手參加。 TopCoder 現(xiàn)場(chǎng)比賽中很重要的一個(gè)創(chuàng)新是:每名比賽選手在觀眾席前都有一個(gè)同步的顯示器,這樣觀眾可以看到選手任何時(shí)刻做的事情,極大增強(qiáng)了互動(dòng)性。
TCCC2006 的 Room 1 和后面的 Final Round 都可謂是死亡之組。現(xiàn)在就回憶一下這兩場(chǎng)激烈的比賽吧。
Room 1?:
至于 3 個(gè)房間的分配, TopCoder 按照注冊(cè)截止時(shí)選手的 Rating 分布蛇形分配。但是 TCCC2006 的房間實(shí)力分布極不平衡,我與上屆冠軍 tomek ,著名選手 reid , Egor , halyavin 還有 Rating 不高但是實(shí)力極強(qiáng)的 Ying 和 ardiankp 同被分到了 Room 1 ,賽前 Room 1 成為公認(rèn)的死亡之組。
在圣地亞哥,我和師兄 Macsy (張一飛)同一個(gè)房間,很感謝師兄的關(guān)心,我那幾天休息的都很好。要知道如果同房的人有 10 小時(shí)左右的時(shí)差的話(huà),一人必須很小心才能保證不影響另一人的休息。
Room 1 在我抵達(dá)美國(guó)的第二天早上進(jìn)行,選手允許提前 30 分鐘準(zhǔn)備一些必要代碼。不過(guò)現(xiàn)在大家都比較喜歡學(xué)習(xí) Petr 那樣一行代碼都不打。下面就是比賽的過(guò)程:
250 分題目是:給定 n(n<=50) 個(gè)整數(shù) AI?和一個(gè)閾值 d ,計(jì)算 n 個(gè)整數(shù)所有排列 PI?中滿(mǎn)足 |API-API+1|<=d 的排列中,所有不同可能 AP1?的個(gè)數(shù)。這題最標(biāo)準(zhǔn)的方法是動(dòng)態(tài)規(guī)劃,基本思想是把 n 個(gè)整數(shù)排序之后,計(jì)算兩條相鄰元素不超過(guò) d 的序列。我使用了一種更精巧的算法,把 n 個(gè)整數(shù)排序之后,對(duì)于 AI?,如果 AI?可能作為排列的第一個(gè)元素,那么 AI?必定在某一個(gè)方向(大小)連續(xù)而在另一個(gè)方向每間隔兩個(gè)元素相連。這個(gè)算法比較容易實(shí)現(xiàn),但是正確性證明比較難,甚至讓人第一感覺(jué)是錯(cuò)的。我寫(xiě)完程序測(cè)試了所有樣例都正確就提交了, 243 分。提交之后我又測(cè)試了許多數(shù)據(jù),并在紙上嘗試證明正確性。
賽后,我看了網(wǎng)絡(luò)上的討論記錄。在我提交 250 分題之后,立刻遭到了 misof 的懷疑,他認(rèn)為我的算法有問(wèn)題。據(jù) Macsy 學(xué)長(zhǎng)的回憶, OpenGL 在我屏幕前看我寫(xiě)完程序,也認(rèn)為我的算法是錯(cuò)的,不過(guò)后來(lái)他們討論之后發(fā)現(xiàn)沒(méi)有反例。
關(guān)掉 250 分題目之后,我剛剛意識(shí)到 Room 1 的 3 題分?jǐn)?shù)不是 250-500-1000 ,而是 250-600-900 。現(xiàn)在看來(lái),對(duì)于 250 比較順利的情況,應(yīng)該先做 500 ,若 250 不順利或者想出奇制勝的話(huà),可以先開(kāi) 1000 分。當(dāng)時(shí)沒(méi)有什么經(jīng)驗(yàn),我認(rèn)為 900 比 600 應(yīng)該簡(jiǎn)單一些,于是就打開(kāi)了 900 。
900 分題目是:給定一張 n(n<=10) 個(gè)點(diǎn)的帶權(quán)有向完全圖(也就是 n2?個(gè)實(shí)數(shù))和一個(gè)衰減系數(shù) p ,求一條經(jīng)過(guò) d(d<=10) 條邊路徑(不需要保證簡(jiǎn)單路徑),要求這條路徑的指數(shù)衰減長(zhǎng)度(指數(shù)衰減是指第 i 段的長(zhǎng)度乘以 pi-1?然后求和)最接近 1000 。這題如果使用窮舉法,就需要 1010?左右的計(jì)算量,在 TopCoder 的測(cè)試機(jī)上也不能通過(guò),由于路徑長(zhǎng)度很容易超過(guò) 1000 ,所以很難找到多項(xiàng)式時(shí)間的動(dòng)態(tài)規(guī)劃。我馬上有了一個(gè)想法 —— 雙向搜索。對(duì)于長(zhǎng)度為 d 的路徑,其實(shí)可以看作從某一個(gè)點(diǎn) p 出發(fā)的一條反向的長(zhǎng)度 [d/2] 的路徑和一條正向的 d-[d/2] 的路徑,對(duì)于固定的節(jié)點(diǎn) v 來(lái)說(shuō),這種兩個(gè)方向的路徑都不超過(guò) n[d/2]?,這樣只要枚舉一個(gè)方向的路徑然后二分查找另一個(gè)方向即可。復(fù)雜度是 O(dn2+[d/2]) 。
現(xiàn)場(chǎng)比賽調(diào)試環(huán)境不是很好,我花了不少時(shí)間調(diào)試以發(fā)現(xiàn)程序中的錯(cuò)誤。提交之后 690 多分,還不到 700 。不過(guò)對(duì)于 900 分的題目在那種壓力下還可以接受。提交之后我花了 15 分鐘左右測(cè)試,沒(méi)有發(fā)現(xiàn)錯(cuò)誤。于是就準(zhǔn)備做 600 了。
600 分題目是:一道經(jīng)典的數(shù)學(xué)題,給定一些盤(pán)子疊放的規(guī)則,計(jì)算頂層盤(pán)子的最大可能大小。其實(shí)算法不是很難,只要二分頂層盤(pán)子的大小,然后依次貪心計(jì)算來(lái)判斷底層是否能夠滿(mǎn)足即可。只是貪心的時(shí)候要考慮兩種情況,一時(shí)想不清楚。我當(dāng)時(shí)已經(jīng)感覺(jué)很疲勞,思路不是很清楚,最后 40 分鐘時(shí)間也沒(méi)能調(diào)試通過(guò)。這題過(guò)于瑣碎, Room 1 中最終沒(méi)有選手通過(guò) 600 分題,并且成就了一個(gè)刺激的 Challenge 階段。
Coding 階段我和 tomek 采用了截然不同的策略,我跳過(guò) 600 直攻 900 ,而 tomek 在 600 中掙扎了很長(zhǎng)時(shí)間才放棄。 Coding 階段結(jié)束時(shí),有 4 名選手提交了 3 題。我依靠速度優(yōu)勢(shì)領(lǐng)先同樣提交 250 和 900 的 tomek 35 分左右。
Challenge 階段開(kāi)始時(shí),我盲 cha ( blind challenge )了一個(gè)最后時(shí)刻提交的 900 分程序,但是由于我選擇的數(shù)據(jù)實(shí)在太弱,失去了 25 分。這樣我和后面的 tomek 只相差 10 分左右了,所以我決定只要 tomek 不動(dòng),我也不動(dòng)了。其實(shí),當(dāng)時(shí) tomek 已經(jīng)知道自己的 900 是錯(cuò)的, Challenge 階段他估計(jì)已經(jīng)放棄了。我的 Challenge 階段最終就以 -25 分結(jié)束。
之后的 Challenge 就是 Ying (王穎)展現(xiàn)勇氣和智慧的舞臺(tái)了。他 Challenge 掉了所有提交的 600 ,憑借 225 分的加分超過(guò)了我,排在榜首。這樣比賽的形式也一目了然了, 7 位選手提交了 900 ,我依靠速度優(yōu)勢(shì)領(lǐng)先第四名 reid 超過(guò) 100 分。只要我兩道題目能夠 Passed System Test 就足以進(jìn)入 Final Round 了。
System Test 之前,我和 Ying 討論他 “ 超神 ” 的 Challenge 階段。這是我第一次參加 TopCoder 的現(xiàn)場(chǎng)比賽,發(fā)現(xiàn) System Test 結(jié)果顯示是按照 System Test 之前的排名倒序進(jìn)行的。測(cè)試到我時(shí),除了 tomek 的 4 名選手的 900 都過(guò)了。顯示我的結(jié)果時(shí),兩個(gè)綠框閃爍了很久終于顯示出了兩個(gè)大大的鉤,我終于可以歡呼慶祝勝利了。我前面的 Ying 也兩題全過(guò)了。這樣我們兩位中國(guó)選手得以在死亡之組攜手出現(xiàn),這場(chǎng)比賽真可謂是中國(guó)選手的勝利。 Reid 只能在 Wildcard 賽再作努力, tomek 則被直接淘汰出局了。
Final Round?:
接下來(lái)的兩天里,我觀看了 Room2 , Room3 和 Wildcard 的比賽。第 2 天晚上我們參加了 TopCoder 贊助的 Laser Tag 游戲,我們所有中國(guó)人組成了一隊(duì),我的發(fā)揮很差,原因是這個(gè)游戲與 CS 不同,選手頭上沒(méi)有感光器,而我喜歡遇到人就攻擊頭部,所以狹路相逢多半是我失敗。活動(dòng)中,我有幸結(jié)識(shí)了許多 Dev 的神人,當(dāng)時(shí)由于 vividmxx 沒(méi)有參加, magicpig 和 PE 的競(jìng)爭(zhēng)很激烈,最終 PE 獲得了 “ 浙江大學(xué)建校 100 年來(lái)第一個(gè) TCCC 冠軍 ” 。記得賽后我 uncle 來(lái)到現(xiàn)場(chǎng),我 uncle 是浙江大學(xué)本科畢業(yè)的, magicpig 見(jiàn)我 uncle 第一句話(huà)就是 “ 浙江大學(xué)建校有 100 年歷史了吧? ” 汗死了。另外 zjq 也獲得了 Design 的亞軍。
第三天中午 Championship Round 開(kāi)始了。決賽時(shí),場(chǎng)地里安裝了很多攝像頭,可以說(shuō)我們的任何舉動(dòng)都在嚴(yán)密監(jiān)視下了。這回我提前確認(rèn)了題目分?jǐn)?shù)是標(biāo)準(zhǔn)的 250-500-1000 的分布。參加決賽的選手除我之外有: andrewzta , ardiankp , bmerry , Eryx , mathijs , Petr 和 Ying 。面對(duì)決賽選手的實(shí)力,我已經(jīng)沒(méi)有意義定一個(gè)類(lèi)似于 “ 保幾爭(zhēng)幾 ” 的目標(biāo)了,努力發(fā)揮自己的水平是最應(yīng)該做的。下面就是比賽的過(guò)程了:
250 分題目是:給定 n 個(gè)正三角形,每個(gè)頂點(diǎn)都有數(shù)字,選出 6 個(gè)三角形拼成一個(gè)正六邊形,要求相鄰的數(shù)字必須相同。三角形允許旋轉(zhuǎn),計(jì)算能夠得到多少個(gè)本質(zhì)不同的正六邊形。題目很長(zhǎng),我仔細(xì)讀了兩遍才開(kāi)始寫(xiě),算法很清楚,就是枚舉六邊形中心和四周的 7 個(gè)數(shù)字,然后判斷是否有足夠的三角形。在判斷本質(zhì)不同的時(shí)候犯了一個(gè)錯(cuò)誤,調(diào)試了幾分鐘,提交之后只有 215 分了,看了一下排名, Petr 有 232 分之高,其他選手都還沒(méi)有提交。測(cè)試了幾分鐘發(fā)現(xiàn)程序的運(yùn)行時(shí)間不是很穩(wěn)健,很容易到達(dá) 0.8 秒左右,測(cè)試了 15 分鐘之多才逐漸放心下來(lái),因?yàn)榛旧纤袛?shù)據(jù)都 0.8 秒左右。賽后 Macsy 告訴我,我的程序速度瓶頸是在 set 的判斷,所以時(shí)間比較穩(wěn)定,不會(huì)超時(shí)。我當(dāng)時(shí)的猶豫和沒(méi)有經(jīng)驗(yàn)浪費(fèi)了至少 20 分鐘的時(shí)間。
按照賽前的計(jì)劃,我這時(shí)應(yīng)該打開(kāi) 1000 的題目的,但是由于自己對(duì) 250 沒(méi)有信心,而且求穩(wěn)思想比較重,我先打開(kāi)了 500 分的題目。現(xiàn)在看來(lái),開(kāi) 500 分的題目并不算錯(cuò)誤,其實(shí)在打開(kāi) 500 分題目的時(shí)候,與 Petr 的差距不是很大。
500 分題目是:給定一個(gè)機(jī)器人的移動(dòng)命令序列,要求計(jì)算結(jié)束時(shí)機(jī)器人的位置。由于移動(dòng)序列中允許 () 這樣的重復(fù)操作,直接模擬是超時(shí)的。這類(lèi)題目的標(biāo)準(zhǔn)算法是利用矩陣乘法,由于之前對(duì)于此類(lèi)題目沒(méi)有經(jīng)驗(yàn),沒(méi)有準(zhǔn)備好就開(kāi)始寫(xiě)了,導(dǎo)致矩陣處理失敗。我果斷放棄了調(diào)試,換用一種記錄中間結(jié)果的搜索方法,寫(xiě)完的時(shí)候已經(jīng)只有 280 分了。更重要的是我已經(jīng)沒(méi)有時(shí)間進(jìn)攻 1000 分了。提交之后排在第 3 ,前面是 Petr 和 Eryx 。
1000 分題目是:給出一個(gè)排隊(duì)取菜的模型,計(jì)算一個(gè)等待時(shí)間的排隊(duì)序列。而且對(duì)于多種答案的情況,要求計(jì)算字典序最小的序列。題目其實(shí)不是很復(fù)雜,集合動(dòng)態(tài)規(guī)劃就可以解決,不過(guò)模擬取菜過(guò)程時(shí)需要非常注意細(xì)節(jié)。 Petr 提交了一個(gè) 660 分左右的程序, Ying 則在最后一分鐘提交了 400+ 分,排在第 2 。
Challenge 階段顯得很枯燥無(wú)味,前兩天大發(fā)神威的 Ying ( +225 )和 Petr ( +300 )都沒(méi)有嘗試 Challenge ,整個(gè) Challenge 階段沒(méi)有任何一個(gè) Successful Challenge 。
System Test 結(jié)果出來(lái)了,在 bmerry , ardiankp 和 andrewzta 都只通過(guò)一題的結(jié)果出來(lái)之后,排在我后面的 mathijs 兩題都 Pass ,隨后我的 250 和 500 也都 Pass 了。但是,排名在我之前的 Eryx 和 Ying 的 500 分和 1000 分都 Failed System Test 了,我瞬間提升到了第二名的位置。不過(guò)雖然 Petr 的 1000 分掛了,但是他依舊憑借 250 和 500 的速度獲得了冠軍。
在這里說(shuō)一下 1000 分的真實(shí)情況吧,因?yàn)檫@些時(shí)間來(lái)對(duì)于 TCCC2006 Final Round 的 1000 分題目有很多不同的說(shuō)法。比賽結(jié)果中顯示沒(méi)有選手通過(guò) 1000 分題,如果仔細(xì)分析測(cè)試結(jié)果, Petr 的程序由于超時(shí)出錯(cuò),而 Ying 的程序由于一個(gè)地方?jīng)]有清 0 而導(dǎo)致錯(cuò)誤,確實(shí)很可惜。因?yàn)槿绻?Ying 的 1000 能夠 Pass 的話(huà),他將是 TCCC 的冠軍。不過(guò) Ying 的算法犯了與造成 Petr 超時(shí)一樣的錯(cuò)誤,他們的動(dòng)態(tài)規(guī)劃程序比標(biāo)準(zhǔn)方法多出一個(gè) n 倍的時(shí)間,我曾經(jīng)成功生成了一個(gè)用例,可以讓 Ying 和 Petr 的程序都超時(shí),這個(gè)例子已經(jīng)得到了 Ying 的認(rèn)可。需要指出的是 TCCC2006 是 TopCoder 的測(cè)試機(jī)的速度還是很慢的,兩個(gè)程序如果在現(xiàn)在的機(jī)子上運(yùn)行可能只需要 1 秒左右了。
比賽之后和 uncle 到 downtown 游玩了一下,參加完頒獎(jiǎng)晚會(huì),第二天就回國(guó)了。
總結(jié):
TCCC2006 是我第一次參加 TopCoder 的現(xiàn)場(chǎng)比賽,很有幸能夠在這么多的第一次中就進(jìn)入決賽并且獲得第 2 名的成績(jī)。很感謝同參加比賽的同學(xué) Macsy , OpenGL , Ying 還有 PMH 的關(guān)心和幫助,你們?cè)谖冶荣悤r(shí)全程在場(chǎng)邊,讓我感覺(jué)很溫暖。
另外,我還有幸認(rèn)識(shí)了 visualage ,現(xiàn)在他已經(jīng)是 arena 的負(fù)責(zé)人了吧。記得他和 OpenGL 在 Room 1 的 Challenge 階段通過(guò)大聲叫中文(在國(guó)外,這是最好的密碼)告訴我 tomek 的 900 是錯(cuò)的,可惜我沒(méi)有聽(tīng)見(jiàn)。
TCCC2006 對(duì)于中國(guó)來(lái)說(shuō)是不小的收獲,中國(guó)選手占領(lǐng)了 Dev 比賽, PE 獲得 “ 浙江大學(xué)建校 100 年來(lái)第一個(gè) TCCC 冠軍 ” , magicpig 和 zjq 分獲 Dev 和 Design 的亞軍,也就是說(shuō)中國(guó)包攬了所有亞軍。在比賽之余,我很高興認(rèn)識(shí)了眾多 TopCoder 的朋友。
Petr 在決賽中表現(xiàn)了非常良好的狀態(tài), TCCC 的奪冠標(biāo)志著 Petr 收獲了 2006 年的大滿(mǎn)貫。 Ying 也采用了很合理的策略,只可惜他的賭博由于運(yùn)氣差一些惜敗。我采用了比較保守的策略,在所有決賽選手中排名第 2 ,這也是我在 TopCoder 的現(xiàn)場(chǎng)賽事中的最高名次了。
TCCC2006 我很感謝家人的關(guān)心,父母凌晨很早起床查看我的比賽結(jié)果,而 uncle 還特地趕來(lái)現(xiàn)場(chǎng)為我加油。這幾年的 TopCoder 現(xiàn)場(chǎng)比賽的贊助商列表里都能找到 American Online(AOL) 的身影, TCCC2006 是 AOL 唯一一次進(jìn)行了 3 個(gè)小時(shí)左右的全程直播,父母和 uncle 都在網(wǎng)絡(luò)上觀看了現(xiàn)場(chǎng)的影像直播。
TCCC2006 我神奇地保持了 100% 的正確率,我個(gè)人認(rèn)為 TopCoder 現(xiàn)場(chǎng)比賽對(duì)正確率提出了更高的要求,我們不必太在意 Coding 階段的那些高分,只要自己的程序是正確的,就是成功的。
利用假期空閑之時(shí),將這幾年 GCJ , ACM , TopCoder 參加的一些重要比賽作個(gè)回顧。回顧 GCJ2006 , ACM2005 , TCCC2006 和 ACM2006 之后,今天簡(jiǎn)要回顧一下國(guó)內(nèi)個(gè)人賽場(chǎng)吧。
國(guó)內(nèi)個(gè)人賽場(chǎng) —— 百度之星
國(guó)內(nèi)個(gè)人賽場(chǎng)中最重要的比賽要數(shù)每年一度的百度程序設(shè)計(jì)大賽,到今年為止已經(jīng)舉辦了 4 屆,每一屆我都全身心地參加了比賽的全過(guò)程,百度程序設(shè)計(jì)大賽是中國(guó)舉辦的規(guī)模最大的公開(kāi)程序設(shè)計(jì)比賽,其參加人數(shù)比許多世界范圍的程序設(shè)計(jì)大賽的人數(shù)還要多得多。另外在 2006 年初, Google Beijing 舉行了 Google Code Jam China 的比賽,剛剛開(kāi)始參加 TopCoder 的我也加入了這次 GCJC 之旅。
第一屆?baidu?程序設(shè)計(jì)大賽:
最早的國(guó)內(nèi)個(gè)人程序設(shè)計(jì)比賽要回憶到 2005 年 9 月開(kāi)始的第一屆百度程序設(shè)計(jì)大賽了,源于宿舍走廊中的海報(bào),我以嘗試的心態(tài)報(bào)名參加了第一屆百度程序設(shè)計(jì)大賽。每一屆百度程序設(shè)計(jì)大賽都由初賽,復(fù)賽和現(xiàn)場(chǎng)決賽組成。
第一屆百度程序設(shè)計(jì)大賽中,印象最深的復(fù)賽題目就是那道規(guī)模巨大的最小樹(shù)形圖問(wèn)題了, 100000 的數(shù)據(jù)規(guī)模嚇退了不少選手,我鼓足勇氣提交了一個(gè)理論上能夠運(yùn)行的程序,順利通過(guò)了復(fù)賽進(jìn)入決賽。最小樹(shù)形圖算法在大多圖論書(shū)上就接在最小生成樹(shù)算法后面,但是其程序量遠(yuǎn)比最小生成樹(shù)大,而且用途沒(méi)有最小生成樹(shù)廣泛,在大多數(shù)競(jìng)賽中很少出現(xiàn)。我最早接觸最小樹(shù)形圖算法是在 2003 年 4 月,當(dāng)時(shí)正在復(fù)旦大學(xué)訓(xùn)練,記得關(guān)于這個(gè)問(wèn)題和 xreborner 討論了很長(zhǎng)時(shí)間才得以證明算法的正確性并實(shí)現(xiàn)出高效的程序。
現(xiàn)場(chǎng)決賽于 2005 年 10 月底在北京舉行,由于當(dāng)年比賽的知名度不高,時(shí)間上還和 GCJ 沖突,沒(méi)有太多的頂尖高手參加。清華大學(xué)除我之外只有 superzn (張寧,我們留 shell 一個(gè)人參加 ACM 北京賽區(qū)預(yù)賽 L ),當(dāng)時(shí) OpenGL 還是以高中生身份參加的,還有復(fù)旦大學(xué)的 xreborner 和 young (李陽(yáng));中山大學(xué)的 magicpig , Savior 和張子臻(不好意思,我不記得您的 ID 了,好像杭州 2008 的時(shí)候我們還說(shuō)起此事)。我一直認(rèn)為,現(xiàn)場(chǎng)比賽過(guò)程的一個(gè)重要的意義在于提供了一個(gè)老朋友重逢和結(jié)實(shí)新朋友的機(jī)會(huì),選手之間的交流是比賽中最重要的組成部分之一,我很有幸能夠在這些比賽中認(rèn)識(shí)了眾多牛人。
稍微回顧一下決賽的題目吧:決賽的題目是經(jīng)典的 8 數(shù)碼問(wèn)題,給定初始狀態(tài)和結(jié)束狀態(tài),計(jì)算最短需要的轉(zhuǎn)移步數(shù)。對(duì)于分?jǐn)?shù)相同的情況,按照程序的運(yùn)行速度排名。比較容易想到的方法有:
(1) 單向 BFS :最壞情況需要 1s 左右。
(2) 雙向 BFS :如果先判斷無(wú)解情況,這是 xreborner 使用的方法,平均情況大概 0.002 秒左右。
(3) A* 或者 IDA* :先判斷無(wú)解情況,然后通過(guò)距離啟發(fā)函數(shù)搜索。平均情況大概 0.002 秒左右。我當(dāng)時(shí)使用了 A* 的方法,但許多地方的實(shí)現(xiàn)不是很合理。
(4) 常量表,這是最有挑戰(zhàn)的方法,因?yàn)闆Q賽的提交量限制在 64K 以?xún)?nèi)。
現(xiàn)場(chǎng)比賽中, (2) 和 (3) 的使用人數(shù)比較多,速度相差無(wú)幾,選手之間比拼的是各種細(xì)節(jié)和常數(shù)的處理。后來(lái),我想出了一種速度非常快的方法:
首先使用 A* 加上 “ 卡節(jié)點(diǎn) ” 技術(shù),就是限制 A* 算法搜索過(guò)程中每層的節(jié)點(diǎn)個(gè)數(shù)上限,這種算法擴(kuò)展節(jié)點(diǎn)個(gè)數(shù)在 100 左右。然后,由于上述算法的正確性不能保證,把所有反例打成常量,程序大概 50K 左右。很容易發(fā)現(xiàn),這個(gè)程序的速度遠(yuǎn)比比賽過(guò)程中所有程序的速度都快得多。
最終我的程序以總時(shí)間 0.022 秒獲得冠軍, xreborner 和 Savior 以 0.026 分并列第二名。 xreborner 的程序很可惜,如果加入了無(wú)解判斷,速度應(yīng)該比我程序塊, superzn 就更可惜了, superzn 的飄逸程序其實(shí)只有 0.020 秒,但是有一個(gè)數(shù)據(jù)錯(cuò)了。
記得頒獎(jiǎng)之后,主持人邀請(qǐng)獲獎(jiǎng)選手發(fā)言,選手可以通過(guò)向前走一步選擇優(yōu)先發(fā)言。這時(shí),我突然感覺(jué)大家把目光都聚焦到了我身上,向右一看,由于我站在最左邊沒(méi)有注意到右邊的情況,可誰(shuí)知其他選手都后退了一步,把我留在了看似向前一步的位置。
第二屆?Astar-baidu?程序設(shè)計(jì)大賽:
第二屆百度程序設(shè)計(jì)大賽沒(méi)有等到 10 月,而是在 2006 年 6 月就拉開(kāi)序幕。沒(méi)有想到的是,第二屆百度程序設(shè)計(jì)大賽竟然以我在一年前比賽中使用的 A* 算法的名字命名,感到非常榮幸。
記得復(fù)賽的題目非常正式,印象最深的要數(shù) xreborner 招牌式的 Zuma ,我推了兩個(gè)小時(shí)公式才得到了正確的動(dòng)態(tài)規(guī)劃方程,實(shí)現(xiàn)之后還由于 TLE 只有 30 分 (100 滿(mǎn)分 ) 。還有 Ying 出的無(wú)向圖最小割問(wèn)題,我用網(wǎng)絡(luò)流算法又超時(shí)了。不過(guò)最后一題,我的程序竟然比 xreborner 優(yōu)化過(guò)的標(biāo)程還快,真是不容易呀。清華的舍友 RealPlayer 在復(fù)賽中表現(xiàn)很興奮,可惜由于一個(gè)很小的錯(cuò)誤沒(méi)能進(jìn)入決賽。
參加第二次百度決賽的選手中有許多熟悉的面孔,清華的同學(xué)包括 shell , OpenGL , lympanda 還有 Macsy 。復(fù)旦大學(xué)也來(lái)了很多選手,其中除了 LemonTree 和 Topkiller (沈毅)之外,還有我剛到復(fù)旦時(shí)見(jiàn)過(guò)的 admin 和 funny 的身影。另外 magicpig 和 flymouse 也參加了,而且 magicpig 和我住一個(gè)房間,吃飯時(shí)記得他把桌上所有人的 Dev 功底全都鄙視了一遍,可惜 PE 不在場(chǎng)呀。比賽前還看到了 Srbga 的身影,據(jù)他說(shuō)是被邀請(qǐng)一起來(lái)玩的,其實(shí)稍微用小腦判斷一下就知道一定是參與出題的,有了 Srbga 的加盟,相信決賽題目絕對(duì)不會(huì)是一年前的風(fēng)格了。
第二年決賽的題目是:著名的俄羅斯方塊。寫(xiě)程序玩一個(gè) 10 列的標(biāo)準(zhǔn) 2 維俄羅斯方塊游戲。
Srbga 設(shè)計(jì)了很有特色的記分方法和評(píng)分標(biāo)準(zhǔn)。對(duì)于記分方法,特別的地方是消去 1 行后沒(méi)有得分,而同時(shí)消去 2 , 3 , 4 行的得分分別是 3 , 6 , 10 ,記分方法非常鼓勵(lì)一次消去多行。評(píng)分標(biāo)準(zhǔn)則更奇怪了,有 50 種不同規(guī)模的數(shù)據(jù),對(duì)于每組數(shù)據(jù)對(duì)所有選手的得分進(jìn)行排名,前 8 名的選手依次得到 10 , 7 , 6 , 5 , 4 , 3 , 2 , 1 分,也就是說(shuō),是存在可能性在測(cè)試結(jié)束之后分?jǐn)?shù)仍然為 0 的。
比賽過(guò)程中,我花了許多時(shí)間來(lái)分析這個(gè)奇怪的評(píng)分標(biāo)準(zhǔn)。
對(duì)于這種評(píng)分標(biāo)準(zhǔn),常見(jiàn)的策略有兩大類(lèi): (1) 所有數(shù)據(jù)的成績(jī)比較平均 (2) 在一種數(shù)據(jù)風(fēng)格中特別突出呢。
根據(jù)數(shù)據(jù)描述, 50 個(gè)數(shù)據(jù)可以分為 10 種不同的風(fēng)格。參加比賽的總共有 50 名選手,如果所有分?jǐn)?shù)是完全平均分配的話(huà),分?jǐn)?shù)是 31 分,這個(gè)數(shù)字意義不大。但如果設(shè)想分?jǐn)?shù)的 80% 會(huì)分配在前 10 名中(根據(jù)當(dāng)時(shí)選手的水平,這個(gè)假設(shè)還是比較合理的),這樣前 10 名的平均分?jǐn)?shù)是 124 分左右,也就是說(shuō)如果想擠進(jìn)前 4 ,至少也要 100 分以上,如果想爭(zhēng)取冠軍估計(jì)需要 200 分左右。如果選擇一種策略,使得它只在一種數(shù)據(jù)風(fēng)格中特別突出,分?jǐn)?shù)只有可憐的 50 分,而且很可能有許多有同樣想法的選手,所以 (2) 不太可取。
在決定選擇比較平衡的策略 (1) 的之后,需要再考慮一個(gè)問(wèn)題,如果最終目標(biāo)是 150 分,那么平均分?jǐn)?shù)只需要 3 分,也就是說(shuō)每個(gè)數(shù)據(jù)可以允許有 5 名選手超過(guò)自己。這些必要的分析幫助我明確了努力的方向,面對(duì)這種開(kāi)放性的題目,多分析題目的特點(diǎn)往往可以達(dá)到事半功倍的效果。
還有一個(gè)重要環(huán)節(jié)是調(diào)整估價(jià)函數(shù),機(jī)器學(xué)習(xí)其實(shí)是一個(gè)很好的策略,可惜我當(dāng)時(shí)不會(huì)。其實(shí)當(dāng)時(shí)我做的事情,本質(zhì)上就是人工模擬機(jī)器學(xué)習(xí),手工調(diào)整了 1 個(gè)半小時(shí),眼都花了。而且我犯下了一個(gè)致命的錯(cuò)誤,記得記分方法非常鼓勵(lì)一次消去多行,也就是說(shuō)對(duì)于平坦的數(shù)據(jù),一次消去 1-3 行的權(quán)值應(yīng)該可能設(shè)置為負(fù)數(shù),而我只把他們?cè)O(shè)成了 0 ,使得程序?qū)τ谄教沟臄?shù)據(jù)分?jǐn)?shù)不高。 Macsy 就考慮到了這一點(diǎn),只可惜一個(gè)很奇怪的技術(shù)問(wèn)題(在 Linux 和 Windows 下的 CLOCKS_PER_SEC 參數(shù)是不一樣大的,想使用卡時(shí)策略時(shí)千萬(wàn)不能事先把這個(gè)數(shù)字取出來(lái)設(shè)置成 CONST )使得 Macsy 沒(méi)能成功。
由于 Macsy 和 LemonTree (同樣的技術(shù)問(wèn)題)的出局,我在許多數(shù)據(jù)中得到了很高的分?jǐn)?shù),最后的總分達(dá)到了是 255 ,領(lǐng)先了第 2 名有 99 分之多。其實(shí)現(xiàn)場(chǎng)的許多選手的程序風(fēng)格相差并不大,可能我唯一多做的事情就是建立了一個(gè)博弈樹(shù),多搜索兩層,這樣比直接貪心的程序看得更遠(yuǎn)一些。后來(lái)事實(shí)也證明了,排名靠前的選手大多都是比較平衡的策略。記得 lympanda 洋洋灑灑寫(xiě)了 1800 多行程序,在其中一種數(shù)據(jù)中拿到了滿(mǎn)分 50 分。不過(guò)可惜 panda 的程序平衡性稍差,總排名進(jìn)入了前 10 ,但最終只有三等獎(jiǎng)。
第二屆 astar-baidu 程序設(shè)計(jì)大賽,復(fù)旦大學(xué)獲得了豐收。記得許多復(fù)旦的選手由于考試提前回到學(xué)校,頒獎(jiǎng)儀式的時(shí)候二等獎(jiǎng)?lì)C獎(jiǎng)一片空?qǐng)觥?/span>
比賽的住宿條件可以用無(wú)與倫比來(lái)形容,很感謝 baidu 的大方與細(xì)心。記得第一天晚上還有機(jī)會(huì)和 Ikki 一起打沙壺球,面對(duì)球風(fēng)完全對(duì)立的 Ikki 玩得很開(kāi)心。
Google Code Jam China 2006
大概是 2005 年末,突然看到了名為 GCJC 的比賽,而且使用的是 TopCoder 的比賽模式,于是就報(bào)名參加了。當(dāng)時(shí)估計(jì)只參加過(guò)幾場(chǎng) TopCoder 的比賽,帳號(hào)還是藍(lán)色的, GCJC 第二輪預(yù)選賽由于經(jīng)驗(yàn)不足差一點(diǎn)就被淘汰了。好在有驚無(wú)險(xiǎn)地進(jìn)入到了北京的現(xiàn)場(chǎng)賽。
GCJC 現(xiàn)場(chǎng)的選手中,我覺(jué)得至少認(rèn)識(shí) 80% 吧,清華同學(xué)就有 7 人: b142857 , fuwenjie , lympanda , Macsy , zig 還有 hyyylr (李老師),復(fù)旦的 LemonTree 和 TopKiller 也都來(lái)了,浙大也來(lái)了許多 TopCoder 上的元老 xuchuan (徐串), sghao126 。
記得,就在 GCJC 決賽的前一天晚上,我參加了 TopCoder 的 SRM 比賽,第一次踩住了 Petr ,不過(guò)也消耗了太多的 RP 。晚上的 SRM 比賽中沒(méi)有人過(guò) 3 題,第二天早上 lympanda 還把我們統(tǒng)統(tǒng)鄙視了一遍。隨后, b142857 還描述他 Challenge 過(guò)程中的囧事,由于 500 分題目的返回結(jié)果需要使用 long long 類(lèi)型,所以 b142857 看到一個(gè)人提交的程序計(jì)算過(guò)程中只使用了 long 就果斷 Challenge 了,結(jié)果失敗了兩次之后才發(fā)現(xiàn),那個(gè)人用的語(yǔ)言是 Java 。
比賽中 250 分題目,簡(jiǎn)單的概率問(wèn)題。我寫(xiě)完就交了 224 分,竟然是所有選手中最快的。后面的 500 分,我雖然提交是最快的,不過(guò)沒(méi)有考慮一種情況。打開(kāi) 1000 分題目之后網(wǎng)絡(luò)就開(kāi)始很不穩(wěn)定了,時(shí)斷時(shí)連, 1000 分題目其實(shí)算法很清楚,由于網(wǎng)絡(luò)原因提交只有 600 分左右了。
Challenge 階段開(kāi)始時(shí),我打開(kāi)了房間中 lympanda 的 500 分程序,發(fā)現(xiàn)我們兩人的程序基本過(guò)程完全一樣。又打開(kāi)了一個(gè),也一樣。但是在還沒(méi)有反應(yīng)過(guò)來(lái)的時(shí)候, lympanda 的 500 分程序被 Challenge 了,接著我的 500 分也被 Challenge 了。然后就沒(méi)有什么斗志了,在無(wú)奈中等待比賽結(jié)束。
比賽結(jié)束之后的午飯過(guò)程中,我正好坐在 Google 中國(guó)掌門(mén)人李開(kāi)復(fù)旁邊。午餐快結(jié)束時(shí),李開(kāi)復(fù)問(wèn)起 2 個(gè)月前的百度程序設(shè)計(jì)大賽,突然,鬼使神差地直接問(wèn)我百度大賽的冠軍是誰(shuí)?這可是在 Google 的老巢呀,抖死了。我當(dāng)時(shí)真害怕他聽(tīng)完回答之后直接把我趕下桌??。
好在我的 250 分和 1000 分都 Pass 了,由于 TopKiller 的 1000 分超時(shí)了,我獲得了第 3 名。冠軍 xuchuan 和亞軍 b142857 都順利通過(guò)了 3 題。
POJ Monthly Contest
大概是從 2004 年 8 月開(kāi)始, POJ 上開(kāi)始舉行每月一次的有獎(jiǎng)月賽。 2005 年的月賽中,每次都有機(jī)會(huì)同 xreborner , Ying 等高手切磋技藝。從 2006 年初開(kāi)始,我已經(jīng)比較熟悉了比賽的題風(fēng),連續(xù)獲得了許多次比賽的冠軍,并且保持了良好的個(gè)人比賽狀態(tài)。
記得 2006 年 4 月底,在 POJ 的郵箱里突然發(fā)現(xiàn)了 hawk 的信,他問(wèn)我五一長(zhǎng)假回家的情況。我告訴 hawk 自己定在周五晚上出發(fā)。于是,第二天早上就看到比賽安排中: 2006 年 5 月份月賽安排在了周五晚上,太囧了。
后來(lái), POJ 上直接出現(xiàn)了一系列奇怪的定義,但其實(shí)結(jié)論就是我不能以正式身份參加月賽了。現(xiàn)在這些定義早已成為笑料了,但是我不參加月賽之后,仍然有 ahyangyi 這樣的選手奪走了絕大多數(shù)的冠軍。
后兩屆?baidu?程序設(shè)計(jì)大賽:
從第二屆開(kāi)始,我們習(xí)慣了在每年 6 月等待 astar-baidu 的開(kāi)賽。 2007 年最出乎意料的就要數(shù) CS 這個(gè)決賽題目了,我在關(guān)鍵的買(mǎi)槍環(huán)節(jié)犯了重要錯(cuò)誤,太迷戀 AK47 了。祝賀師兄 lympanda , Macsy 還有 shell ,不愧是真金不怕火煉。
第四屆百度大賽我參與了預(yù)賽和復(fù)賽的命題工作,但是沒(méi)有參與決賽的命題。決賽題目是一道關(guān)于直升機(jī)的題目,印象最深的是 ahyangyi 使用了一個(gè)很有進(jìn)攻性的策略,如果采用淘汰賽,可能就是冠軍了。對(duì)我來(lái)說(shuō),通過(guò)現(xiàn)場(chǎng)比賽,有機(jī)會(huì)和老朋友重逢,并結(jié)識(shí)了許多新選手是我最大的幸事。
利用假期空閑之時(shí),將這幾年 GCJ , ACM , TopCoder 參加的一些重要比賽作個(gè)回顧。今天到了 2007 年初的東京,回顧一下 2007 世界總決賽發(fā)生的趣事吧。
ACM-ICPC World Final 2007 —— Mobile Robot 東京決戰(zhàn)
2007 年的東京 ACM-ICPC 全球總決賽在櫻花盛開(kāi)的 3 月初拉開(kāi)序幕。成立了一年的 Mobile Robot 憑借 2006 年 ACM 上海賽區(qū)的冠軍,代表清華參加了此次 ACM 盛會(huì)。
記得黃金雄教授在杭州 2008 時(shí)說(shuō), ACM 總決賽的實(shí)力分布由原先的美洲獨(dú)霸逐漸轉(zhuǎn)向了現(xiàn)在的亞歐爭(zhēng)霸。 2007 年,同樣來(lái)自亞洲的上海交大具有很強(qiáng)的奪冠實(shí)力,歐洲 2007 年雖然沒(méi)有頂尖高手 Petr 和 tomek 的參與,但是 ACM 傳統(tǒng)名校 St. Petersburg , St. Petersburg IMFO , Warsaw , Saratov , Petrozavodsk 等都派出了極其豪華的陣容。雖然在 2000 年前后美洲隊(duì)伍成績(jī)不佳,但是近些年由于眾多歐洲選手的加盟,美洲 MIT 等頂尖名校也在總決賽中表現(xiàn)得非常強(qiáng)勢(shì)。
記得,每次世界總決賽之前, TopCoder 的論壇上都會(huì)羅列出所有參加總決賽的 TopCoder 選手名單。但是我不是很看重這些數(shù)據(jù),因?yàn)樵诤芏啻闻c歐洲選手切磋之后,我發(fā)現(xiàn)了自己與歐洲選手相比的一個(gè)重大缺陷:我參加各類(lèi)賽事以來(lái),起初比賽過(guò)程中常常受壓力的影響很大,很難正常發(fā)揮自己的水平。后來(lái)情況有所好轉(zhuǎn),在大多數(shù)比賽中都能正常發(fā)揮自己的水平。可是,令我感到意外的是,許多來(lái)自西方的選手在巨大的壓力下,反而表現(xiàn)得極其興奮而能超常發(fā)揮出自己的水平。來(lái)自西方的各隊(duì),我相信他們只要達(dá)到了興奮的狀態(tài),都擁有獲得冠軍的實(shí)力。去年上海交大總決賽總結(jié)中,他們也提到了自己沒(méi)有發(fā)揮出應(yīng)有的水平,而 IMFO 即使在比賽壓力下仍然能夠做出 8 題,可見(jiàn)他們平時(shí)訓(xùn)練實(shí)力之強(qiáng)。但是我覺(jué)得現(xiàn)場(chǎng)比賽發(fā)揮受影響可能是少數(shù)中國(guó)選手的壞習(xí)慣,可能不適合用同樣的思路分析歐洲的頂尖高手。
抵達(dá)東京:
出發(fā)的前一天晚上,我仍然熬夜參加了 TopCoder 上的 SRM 比賽,竟然是 Petr 出的題目。當(dāng)時(shí)我與 Petr 的 Rating 差距很小,當(dāng)時(shí)我 3 道題目都交出了很高的分?jǐn)?shù),在 System Tests 之前遙遙領(lǐng)先,但是 500 和 1000 分的題目都由于一些很小的粗心而失敗了。我也失去了在總決賽之前超過(guò) Petr 的大好機(jī)會(huì)。結(jié)果到達(dá)日本之后的第二天,吃早餐的時(shí)候,我就碰到了作為教練來(lái)到東京的 Petr ,他一看到我就扯前天比賽的事情,汗。現(xiàn)在回想起來(lái),那場(chǎng) SRM 對(duì)我的總決賽之旅確實(shí)有不小的負(fù)面影響。
抵達(dá)東京之后才發(fā)現(xiàn),所有隊(duì)伍中,只有我們選擇了與所有志愿者衣服顏色相同的清華校色紫色,開(kāi)幕式過(guò)程中,許多隊(duì)伍都把我們當(dāng)成志愿者了。
練習(xí)賽前一天的晚會(huì)很豐盛,大多食物都是中國(guó)風(fēng)格的,水果也非常好吃。晚會(huì)期間,我見(jiàn)到了眾多大陸學(xué)校的隊(duì)伍,當(dāng)年大陸至少有 15 支隊(duì)伍參加總決賽,隨處可以感覺(jué)到說(shuō)著國(guó)語(yǔ)的選手。同時(shí)還見(jiàn)到了許多 TCCC 上出現(xiàn)過(guò)的面孔,隨后發(fā)現(xiàn) ardiankp 也來(lái)參加了,我們還聊起了 ACM 在新加坡( ardiankp 是代表南洋理工大學(xué)參加的)的情況。類(lèi)似總決賽這樣的比賽,我覺(jué)得選手之間的交流則更重要了,因?yàn)槊看慰倹Q賽都會(huì)集結(jié)眾多熟悉的 ID 但陌生的面孔。晚一些之后,我們與北京大學(xué)的 T2 一起打牌,隊(duì)友 geworm 和 wd.h 都抽簽到了另一方,他們的牌太猛了,在加上我和李文新老師的牌都不好,結(jié)果我們慘敗。
從正式比賽的前一天的中午開(kāi)始,主辦方組織我們游玩當(dāng)?shù)氐?Disney 樂(lè)園。日本 3 月的景色很美,當(dāng)?shù)厝艘埠軣崆?#xff0c;唯一的缺點(diǎn)就是無(wú)論用日語(yǔ)還是日式英語(yǔ)都很難交流。我們?cè)?Disney 樂(lè)園中主要以觀看表演為主,沒(méi)有參與過(guò)多的活動(dòng)。東京到了晚上有些冷,我嘴唇都有些結(jié)冰了,可是發(fā)現(xiàn)路上許多日本女高中生還穿著裙子,仰慕。
正式比賽:
總決賽的隊(duì)伍是按照學(xué)校的音序排座位的,練習(xí)賽時(shí)我們發(fā)現(xiàn)自己坐在來(lái)自荷蘭的上屆亞軍 Twente 大學(xué)旁邊,剛打招呼就發(fā)現(xiàn)他們 3 人的最低身高也有 190 ,據(jù)說(shuō)荷蘭女子的平均身高也有 180 以上,似乎覺(jué)得自己是從小人國(guó)來(lái)的。
練習(xí)賽過(guò)程中,我已經(jīng)絲毫感受不到娛樂(lè)的氣息了,現(xiàn)場(chǎng)的緊張氣氛已經(jīng)籠罩了我們?nèi)?duì)。所有隊(duì)伍都在抓緊一分一秒熟悉比賽環(huán)境,賽場(chǎng)中敲擊鍵盤(pán)的聲音已經(jīng)完全覆蓋了觀眾鼓掌的聲音。比賽中使用的 PC2?提交系統(tǒng)比想象得穩(wěn)定,我們努力嘗試各種功能以熟悉機(jī)子上的編程環(huán)境。東京的總決賽使用了一個(gè)形狀奇特的鍵盤(pán),由于當(dāng)時(shí)早已養(yǎng)成了自帶鍵盤(pán)的習(xí)慣,這次總決賽中奇形怪狀的鍵盤(pán)對(duì)我編程的速度影響非常大。
總決賽正式比賽在第二天 9 點(diǎn)左右開(kāi)始, Bill 想盡各種辦法活躍氣氛,不過(guò)比賽開(kāi)始前幾分鐘現(xiàn)場(chǎng)還是靜得可怕,比賽開(kāi)始 5 分鐘之后,現(xiàn)場(chǎng)就被鍵盤(pán)聲籠罩直到結(jié)束。我們回顧一下比賽的過(guò)程吧,底紋的文字是我比賽后寫(xiě)下的總結(jié):
這次 World Final 的題目又基本由編程題組成,可能是由于比賽時(shí)不夠興奮,比賽全程都非常不順利。
大概從 2003 年開(kāi)始,世界總決賽的題目風(fēng)格已經(jīng)完全倒向以編程題為主的特點(diǎn),對(duì)此我們?cè)缬袦?zhǔn)備。不過(guò)由于時(shí)差問(wèn)題,還有幾天前 SRM 比賽由于錯(cuò)兩題導(dǎo)致 Rating 跌停對(duì)我信心的影響,使我比賽中一直不是很興奮。不過(guò)比賽過(guò)程中,我們?nèi)匀粓?jiān)定的采用前面提到過(guò)的常用組隊(duì)模式:
(1) geworm 全程負(fù)責(zé)讀題,思考算法和出數(shù)據(jù);
(2) wd.h 和我在比賽前 2 個(gè)小時(shí)一起攻簡(jiǎn)單的題目;
(3) 2 小時(shí)后 wd.h 就開(kāi)始死磕難題,我主寫(xiě)程序一直到 3 個(gè)半小時(shí)左右,結(jié)合 wd.h 對(duì)難題的把握,大家開(kāi)始合攻難題。
25 分鐘: Problem A ,簡(jiǎn)單地枚舉。可是我生物沒(méi)有學(xué)好,沒(méi)有考慮父母基因的順序問(wèn)題,錯(cuò)了一次。
比賽開(kāi)始時(shí),正常情況我會(huì)從 B-I 中間尋找容易上手的題目。可是由于有些緊張,直到 geworm 給我翻譯 A 題目?jī)?nèi)容時(shí),我還沒(méi)有讀懂任何題目,這種情況很少發(fā)生。
題目 A 的描述,需要一些必要的生物知識(shí)幫助理解,可是這些東西我早已忘記。 geworm 花了不少時(shí)間幫助我理解這題,我還是由于沒(méi)有考慮父母基因的順序 WA 了一次。不過(guò)改過(guò)來(lái)之后,我們竟然是所有隊(duì)伍中第一個(gè)通過(guò) A 題的,可見(jiàn)當(dāng)時(shí)很多隊(duì)伍也沒(méi)有完全放開(kāi)。
43 分鐘: Problem B ,最長(zhǎng)上升子序列。開(kāi)始算法沒(méi)有想好,莫名其妙地錯(cuò)了一次。
如果說(shuō)題 A 的 WA 是生物問(wèn)題,那 B 的 WA 簡(jiǎn)直就是莫名其妙。 B 就是最長(zhǎng)上升子序列問(wèn)題,好像剛開(kāi)始寫(xiě)時(shí)我和 wd.h 都沒(méi)有想清楚,寫(xiě)了一個(gè)神鬼莫測(cè)的程序, WA 一次之后才改成正確算法。可是當(dāng)時(shí)我們都沒(méi)有想到的,總決賽中我們隊(duì)伍莫名其妙的 WA 噩夢(mèng)才剛剛開(kāi)始。
97 分鐘: Problem G ,枚舉 + 模擬。這是很扯淡的一題,題目很容易看錯(cuò),我們由于看錯(cuò)題目錯(cuò)了兩次,等看到 Twente 大學(xué)過(guò)了之后才重讀題目,找到了正確的理解,浪費(fèi)了大量的時(shí)間。
G 的題目描述確實(shí)不是很清楚,許多隊(duì)伍都發(fā)生了理解錯(cuò)誤,我們也不例外。不過(guò)第 2 次提交錯(cuò)誤就不能理解了,當(dāng)時(shí)也不知道出于什么原因又提交了第二次,難道是想先搶一個(gè)提交冠軍嗎?當(dāng)時(shí)我們確實(shí)受到了開(kāi)局不順利的影響,這樣做在罰時(shí)本身就落后的情況更是下雪上加霜。
146 分鐘: Problem F , BFS 。其實(shí)這題是我發(fā)揮編程能力的機(jī)會(huì),但是我開(kāi)始用了一個(gè)很奇怪的搜索方法,錯(cuò)了一次才改用 BFS 過(guò)了。
在 G 題迷茫而放棄之后,我又嘗試實(shí)現(xiàn)了 F 。 F 的第一次 WA 是我們 Final 之行的第三次 “ 莫名其妙 ” 了,我也不知道自己用了什么一種奇怪的搜索方法竟然過(guò)了樣例,還馬上提交了,面對(duì)這種情況我有些著急,表現(xiàn)得很不冷靜。好在 geworm 及時(shí)提醒,我馬上改成 BFS 過(guò)了。在這期間, wd.h 已經(jīng)實(shí)現(xiàn)出了 I 題,并提交了一次,結(jié)果是 WA 。
178 分鐘: Problem C ,排序 + 枚舉。這題有一個(gè)陰險(xiǎn)的地方,就是 theta=0 的情況,還好我們考慮到了,這也是我們唯一一次 AC 的題目了。
C 題的算法其實(shí)非常清楚,陰險(xiǎn)的情況我們也考慮到了,我終于沒(méi)有再搞笑一次,這也是我們唯一一次 AC 的題目了。從通過(guò) C 的時(shí)刻講,我們的形式還是很有利的,因?yàn)殡y度很大的 I 我們已經(jīng)實(shí)現(xiàn)得差不多了。
224 分鐘: Problem D ,數(shù)學(xué)題。這題本是一道很簡(jiǎn)單的數(shù)學(xué)題目,但是不知出題人怎么想的,搞了一些沒(méi)有任何意義的東西,真是這次題目的一大敗筆。我們開(kāi)始由于沒(méi)有注意三點(diǎn)共線的情況錯(cuò)了 3-4 次,然后由于 int64 越界又錯(cuò)了 3-4 次,最后錯(cuò)了 7 次才 AC 。這題一共浪費(fèi)了 1 個(gè)多小時(shí)。
在 BGF 各一次奇怪的 WA 之后,我們又完全陷在了 D 題的陷阱之中,如果順利的話(huà) D 題只需要 15 分鐘就可以寫(xiě)完,可是我們忘記考慮了 D 題中很多的陰險(xiǎn)情況,拖延了 1 個(gè)多小時(shí),貢獻(xiàn)了 7 個(gè)莫名其妙的 WA 。可是,當(dāng)時(shí)我并沒(méi)有想到,這已經(jīng)是我 AC 的最后一道題目了。
227 分鐘: Problem I ,數(shù)學(xué) + 模擬。這題是 Jelly 寫(xiě)的,有很多特殊情況。
平心而論,我在總決賽上的狀態(tài)不是很好,編程速度受到影響,而且有 10 次以上的錯(cuò)誤提交。最后我們 7 題的罰時(shí)高達(dá) 1200 多,而上海賽區(qū)同樣 7 題的罰時(shí)只有 700 多,從這一點(diǎn)上也可以看出當(dāng)時(shí)實(shí)在不在狀態(tài)。不過(guò), wd.h 很好地執(zhí)行了我們預(yù)定的組隊(duì)模式,順利完成了拖后中衛(wèi)的角色。在我通過(guò) D 題之后,他改正了 I 程序中的最后一個(gè) bug 。 I 題最終也只有我們和華沙兩支隊(duì)伍通過(guò),可是說(shuō)是我們最終能夠獲得亞軍的殺手锏。記得在頒獎(jiǎng)儀式之前,基本上所有選手見(jiàn)到我都問(wèn) I 怎么做,我都統(tǒng)一回答:是胡偉棟做的。
我們依靠 I 題的 AC 首次排在了榜首。比賽進(jìn)行了 227 分鐘,能夠在 200 分鐘之后獲得領(lǐng)跑的機(jī)會(huì),我首次看到了奪冠的希望,上海和西安賽區(qū)的歡呼場(chǎng)面一次又一次從我眼前閃過(guò)。當(dāng)時(shí)只有華沙大學(xué)通過(guò) 6 題,其他隊(duì)伍都還不超過(guò) 5 題。
可是幸福只持續(xù)了短暫的 3 分鐘,我們由于罰時(shí)太多而被華沙反超,華沙大學(xué)通過(guò)第 7 題時(shí)華沙隊(duì)員的反應(yīng)幾乎瘋狂, ICPC 的工作人員也用照片記錄了這一時(shí)刻。
Problem E ,我們的算法應(yīng)該是正確的:二分答案 + 最短路。但是不知程序犯了什么錯(cuò)誤,沒(méi)有 AC 。
Problem H ,很復(fù)雜的幾何題目,我們的算法是:掃描。但是不知程序又哪里寫(xiě)錯(cuò)了,結(jié)果是 WA ,不是 TLE 。
雖然在接下來(lái)的 73 分鐘時(shí)間內(nèi)我們沒(méi)有再過(guò)題,不過(guò)我們?nèi)匀晦諝⒌搅俗詈笠豢?#xff0c;拼盡全力而無(wú)怨無(wú)悔。無(wú)論是 E 還是 H ,我們都想出了正確的算法,并且成功寫(xiě)完了程序,但是 Judge 給出的結(jié)果一直是 WA 。我們不斷測(cè)試數(shù)據(jù),并修正了一些 bug ,但仍然不能通過(guò)第 8 題。在這種情況下的穩(wěn)定過(guò)題能力我們確實(shí)特別沒(méi)有訓(xùn)練過(guò),華沙能夠通過(guò) 8 題的超強(qiáng)實(shí)力確實(shí)很讓人敬佩。比賽剛結(jié)束時(shí), Petr 還特地趕來(lái)問(wèn)我們有沒(méi)有通過(guò)第 8 題, ICPC 的工作人員碰巧留下了照片。
當(dāng)時(shí)我很希望能夠借他的運(yùn)氣得到一個(gè) Yes ,不過(guò) PC2?還是不斷返回 WA 直到最后。
后來(lái), E 題就成了我寫(xiě)計(jì)算幾何題目的一個(gè)巨大的心理障礙,直到 2 個(gè)月前在 Proxima 的一次訓(xùn)練中,在隊(duì)友的支持下,我終于成功通過(guò)了一個(gè)更強(qiáng)版本的 E 題(題目在 UVA 上,題號(hào)是 11425 ,這題至今 2009.1 也還只有我和東京冠軍隊(duì)的 marek 通過(guò))。
Problem J ,這是一道很復(fù)雜的算法題目,現(xiàn)在我還不能證明算法的正確性。更重要的是這題很容易實(shí)現(xiàn)一些看似正確的算法,可能沒(méi)有做這題是我們這次比賽的唯一成功之處。
I 的算法大致如下:
(1) X_i = the mininum cut between V_i and V_0.
(2) while (the graph is not empty)
{
(3) m = min(X_i).
(4) remove all nodes V_i whose X_i=m.
(5) let X_i = min( X_i , m+ the mininum cut between V_i and V_0 ).
}
(6) return X_1.
這里提一個(gè)公開(kāi)的秘密,最后顯示華沙大學(xué)的結(jié)果時(shí),他們成功通過(guò)了 E 題,可是比賽過(guò)程中,我們并沒(méi)有看到他們掛起藍(lán)色的氣球,不知道來(lái)自浙江大學(xué)或者中山大學(xué)的選手能不能仔細(xì)回憶一下,當(dāng)時(shí)你們應(yīng)該坐在他們旁邊。
頒獎(jiǎng):
最終,華沙大學(xué)以通過(guò) 8 題的成績(jī)獲得冠軍, Mobile Robot 通過(guò) 7 題總用時(shí) 1200 分鐘獲得亞軍。整場(chǎng)比賽,我們克服了開(kāi)局的種種不利因素,成為全場(chǎng)第一支通過(guò) 7 題的隊(duì)伍,亞軍也是一個(gè)非常可喜的成績(jī)了。由于華沙大學(xué)不來(lái)自亞洲,我們同時(shí)也獲得了亞洲冠軍。
頒獎(jiǎng)儀式之后的表演很精彩,印象最深的要數(shù)那位 “ 神偷 ” 了,他在觀眾面前不斷施展 “ 妙手空空 ” ,觀眾掌聲不斷。記得表演結(jié)束后大家等電梯時(shí),那位演員從我們身邊走過(guò),我們都連忙確認(rèn)自己的錢(qián)包和手機(jī)。 ACM-ICPC 東京總決賽在一片片掌聲中落下帷幕。
總結(jié):
ACM-ICPC 總決賽結(jié)束后, Mobile Robot 又恢復(fù)了平靜。 Mobile Robot 成立以來(lái)共獲得了兩個(gè)分區(qū)賽冠軍和一個(gè)總決賽亞軍,從那之后 Mobile Robot 就宣布解散了,也許唯一的遺憾就是沒(méi)能獲得一個(gè)真正的世界冠軍。賽后,黃金雄教授也來(lái)向我們祝賀,從他的言語(yǔ)中,我們也感受到了一絲揮之不去的遺憾。
東京總決賽的幾天里,我有機(jī)會(huì)結(jié)識(shí)了許多國(guó)內(nèi)外朋友,也是這次日本之行的一大收獲。同時(shí)也感謝眾多 ACM 選手一年來(lái)對(duì)我們的關(guān)心和支持,當(dāng)時(shí) bbs.pku 上留下了一個(gè)很長(zhǎng)的帖子,讓我永生難忘。
在現(xiàn)場(chǎng)比賽中,我數(shù)次與歐洲選手直接交手,對(duì)他們的特點(diǎn)有一定的了解:
(1) 歐洲選手的編程能力很強(qiáng),很適應(yīng)總決賽現(xiàn)有的題目風(fēng)格。有些歐洲選手在 notepad 里寫(xiě)程序,然后直接提交的事跡絕非傳說(shuō)。
(2) 歐洲選手對(duì)于算法的靈活運(yùn)用能力強(qiáng),但是對(duì)于一些比較深的算法了解不多。例如此次總決賽的 J 題。
(3) 許多歐洲選手的現(xiàn)場(chǎng)抗壓能力很強(qiáng),即使在最后時(shí)刻仍然可以發(fā)揮出自己的水平。
在總結(jié)過(guò)復(fù)旦和 Srbga 出題的風(fēng)格之后,總結(jié)一下我理解的總決賽題目風(fēng)格吧:
(1) Srbga 大哥出的題目和世界總決賽的題目風(fēng)格近似,題目對(duì)編程能力提出了極高的要求。相比之下大多數(shù)題目對(duì)算法的要求不高。
(2) 總決賽題目對(duì)算法的考察范圍非常廣,但是對(duì)于某特殊的算法要求不高。
(3) 總決賽題目的時(shí)間限制很寬,出題人很提倡一題多解。而且數(shù)據(jù)沒(méi)有想象得苛刻,隨機(jī)算法有用武之地。
東京的總決賽已經(jīng)結(jié)束快 2 年,今年寒假結(jié)束之后,我又要準(zhǔn)備踏上總決賽征程了,希望這次我們 Proxima 能做的更好,將總決賽名次提高一位。
利用假期空閑之時(shí),將這幾年 GCJ , ACM , TopCoder 參加的一些重要比賽作個(gè)回顧。今天總結(jié)一下國(guó)際個(gè)人賽場(chǎng)吧。
國(guó)際個(gè)人賽場(chǎng) —— 三大賽事
ACM-ICPC 總決賽結(jié)束后, Mobile Robot 就宣布解散了,也許唯一的遺憾就是沒(méi)能獲得一個(gè)真正的世界冠軍。宣布退役 ACM 之后,我仍然連續(xù)參加了那之后的每一場(chǎng)世界范圍的現(xiàn)場(chǎng)編程比賽,按照時(shí)間先后分別是: TopCoder Open( 簡(jiǎn)稱(chēng) TCO)2007 , TopCoder Collegiate Challenge ( 簡(jiǎn)稱(chēng) TCCC)2007 , TCO2008 以及 Google Code Jam( 簡(jiǎn)稱(chēng) GCJ)2008 。每次比賽,我都度過(guò)了一段美好快樂(lè)的時(shí)光。
TopCoder?公司與三大賽事:
TopCoder 公司大概在 9 年前成立,成立的原因有些讓人匪夷所思,據(jù)說(shuō)公司創(chuàng)立者原來(lái)是另一家 IT 公司的大股東,在把原來(lái)公司的股票轉(zhuǎn)手之后換了一筆錢(qián),開(kāi)設(shè)了 TopCoder 公司。然而 Topcoder 和原來(lái)的 IT 公司有一個(gè)重要協(xié)議,就是 Topcoder 在創(chuàng)立之初的兩年內(nèi)不得從事軟件開(kāi)發(fā)的工作。于是 TopCoder 在前兩年時(shí)間內(nèi)以類(lèi)似競(jìng)賽的方式從事軟件開(kāi)發(fā)的活動(dòng)。經(jīng)過(guò) 9 年的發(fā)展,現(xiàn)在 TopCoder 公司已經(jīng)基本由算法競(jìng)賽轉(zhuǎn)向軟件開(kāi)發(fā)了。
TopCoder 公司除了在網(wǎng)上舉辦 SRM 之外,每年還舉辦 TCO 和 TCCC 等現(xiàn)場(chǎng)賽事(當(dāng)然還有 TCHS ,不過(guò)規(guī)模比較小,參與面也不是很大), TCO 和 TCCC 分別在每年的 6 月和 11 月舉行,每次大賽都能匯聚眾多國(guó)際編程高手。另外, Google 公司從 2000 年開(kāi)始,先在各大洲舉辦名為 Google Code Jam 的比賽,從 2002 年開(kāi)始也舉辦全球范圍的 Google Code Jam 。于是這些年來(lái),大家一直把 TCO , TCCC 和 GCJ 稱(chēng)為三大賽事。
2007 年之前的 GCJ 都是使用 TopCoder 的比賽形式, Topcoder 的算法競(jìng)賽有點(diǎn)類(lèi)似于 IOI , ACM-ICPC 之類(lèi)的競(jìng)賽,題目是同一個(gè)類(lèi)型的。每次比賽三道題目,一般分?jǐn)?shù)分配為 250-500-1000 ,比賽分為 Coding , Rest , Challenge 和 System Test 四個(gè)階段,時(shí)間各是 75 分鐘(現(xiàn)場(chǎng)比賽 85 分鐘), 5 分鐘, 15 分鐘(現(xiàn)場(chǎng)比賽 10 分鐘)和不定。
TopCoder 的現(xiàn)場(chǎng)比賽都由 3 個(gè)階段組成:所有選手被分為 3 個(gè)組(稱(chēng)為 Room1 , 2 , 3 ),每組分別進(jìn)行半決賽,每組前 2( 或 3) 名直接晉級(jí)決賽, 3-6 名晉級(jí) wildcard 比賽, wildcard 比賽 12 人中的前兩名填補(bǔ)決賽的最后 2( 或 1) 個(gè)名額,決賽由 8( 或 10) 名選手參加。由于三大賽事的比賽形式相差不大,每次現(xiàn)場(chǎng)決賽的選手中總是有許許多多熟悉的面孔。
三大賽事的波蕩起伏:
可能細(xì)心的同學(xué)能夠發(fā)現(xiàn)疑問(wèn),在文章最開(kāi)始的一段中,我表明自己在 2007 年之后沒(méi)有錯(cuò)過(guò)任何現(xiàn)場(chǎng)賽事,那為什么沒(méi)有 GCJ2007 呢?其實(shí)原因很簡(jiǎn)單, Google 公司在 2007 年全年中只舉辦了面向美洲的比賽,沒(méi)有舉行面向全世界的公開(kāi)賽。 GCJ2007 的擱淺也使得整個(gè) 2007 年只有 TopCoder 公司獨(dú)自舉辦世界大賽。
但是,當(dāng)大家以為 GCJ 將在記憶中淡去的時(shí)候, GCJ2008 重新登陸,而且新的比賽環(huán)境與形式給選手以煥然一新的感覺(jué)。這里先談?wù)勛约簩?duì)這種新比賽環(huán)境的看法吧:
GCJ2006 仍然使用的是 TopCoder 標(biāo)準(zhǔn)形式,也就是說(shuō)和 TCO 以及 TCCC 完全一樣,用一句話(huà)概括就是 Coding-250-500-1000-Challenge-SystemTests 。
GCJ2008 比賽環(huán)境結(jié)合了 ACM , TopCoder 還有 IPSC(ipsc.ksp.sk) 等多種比賽的特色。
(1) 每道題目分為 Easy-Hard 兩組數(shù)據(jù),并且數(shù)據(jù)可以下載到本地,這點(diǎn)好像與 IPSC 很相似,另一個(gè)與 IPSC 的共同點(diǎn)就是,不限制選手使用的編程工具,包括肉眼觀察或者人工搜索。
(2)Easy 數(shù)據(jù)則和 ACM 非常近似,即時(shí)提交評(píng)測(cè),并且也設(shè)定了每次失敗提交加 4 分鐘的罰時(shí)。
(3)Hard 數(shù)據(jù)則更像 TopCoder 的形式了, Hard 數(shù)據(jù)由于是統(tǒng)一評(píng)測(cè), System Tests 可以有效
地把懸念保留到最后一刻。
GCJ2008 的比賽形式是一種大膽的嘗試,并且也已經(jīng)有了很理想的結(jié)果。
另外,值得稱(chēng)贊的是, GCJ2008 中首次使用了分各大洲進(jìn)行當(dāng)?shù)噩F(xiàn)場(chǎng)半決賽的賽制。使得排在前 500 名的選手得以參加各大洲的半決賽,也拉近了 Google 公司與選手之間的距離。從另一個(gè)角度來(lái)說(shuō),各大洲半決賽的方法很有效保證了決賽選手的水平。平心而論, TopCoder 現(xiàn)場(chǎng)比賽前的最后一輪網(wǎng)絡(luò)淘汰賽對(duì)選手的壓力很大,就連 Petr 在 2007 年都直接來(lái)了一個(gè) “ 滑鐵盧 ” ,連現(xiàn)場(chǎng)賽都沒(méi)有進(jìn)。而現(xiàn)場(chǎng)比賽的公平程度遠(yuǎn)超過(guò)網(wǎng)絡(luò)賽,所以通過(guò)現(xiàn)場(chǎng)賽決定決賽選手可以一定程度上提高決賽選手的水平,至少我個(gè)人很贊同這種做法。
擱淺的比賽無(wú)獨(dú)有偶,可能是受到了 2008 年全球經(jīng)濟(jì)危機(jī)的影響, TCCC2008 也停辦了。而且我們都覺(jué)得, TCCC2007 很可能是 TopCoder 舉行的最后一次 TCCC 了,當(dāng)然 TopCoder 這樣做沒(méi)有不合理的地方。
TCO 則相對(duì)穩(wěn)定一些,就連每年舉行的地點(diǎn)都不變, TCO 連續(xù) 3 年在著名的賭城 Las Vegas 舉行。今年應(yīng)該也不會(huì)改變地點(diǎn)。
三大賽事的舉辦,我覺(jué)得選手最大的受益就是,比賽提供了一個(gè)到美國(guó)免費(fèi)游玩的機(jī)會(huì)。我先后去過(guò) 7 次美國(guó),其中 6 次都是參加編程比賽。通過(guò)比賽的機(jī)會(huì),我們得以開(kāi)闊眼界,結(jié)交朋友。我個(gè)人真心希望三大賽事能夠繼續(xù)舉行,但是 2009 年秋天的 TCCC 和 GCJ 很可能同時(shí)停辦,這也是一個(gè)不可回避的問(wèn)題,讓我們拭目以待吧。
美國(guó)之旅:
從 2007 年以來(lái)的 4 次現(xiàn)場(chǎng)比賽,雖然每次比賽過(guò)程中都有一些遺憾,但是現(xiàn)在回想起來(lái)都有不盡的樂(lè)趣。
TCO2007 是我第一次到達(dá)賭城,一下飛機(jī)就看到很多賭場(chǎng) (CASINO) ,可誰(shuí)知 TCO2007 整個(gè)比賽過(guò)程就是一場(chǎng)巨大的賭博。我當(dāng)時(shí)由于不熟悉 Texas Hold'em 的規(guī)則,在半決賽中搞錯(cuò)了 Flush 和 Straight 的大小關(guān)系,結(jié)果初上賭場(chǎng)就傾家蕩產(chǎn)而被淘汰出局。 TopCoder 比賽中竟然出賭博有關(guān)的題目,果然有 Las Vegas 的特色呀。不過(guò)在賭場(chǎng)里,我仔細(xì)研究了許多賭博游戲的規(guī)則,然后寫(xiě)了幾個(gè)程序計(jì)算賭博的期望,但是發(fā)現(xiàn)標(biāo)準(zhǔn)概率模型下所有游戲的期望值全是負(fù)數(shù)(其實(shí)挺顯然的),于是,也就以?shī)蕵?lè)為目的和 lympanda 切磋了一下。
如果說(shuō) TCCC2006 的 Room1 是中國(guó)的勝利, TCO2007 的 Room1 則是中國(guó)的失敗了,雖然 Ying 和 lympanda 都進(jìn)入了 wildcard ,可是都由于一些小失誤輸?shù)袅诉@次賭博。賽后 lympanda 請(qǐng)我去牛排館吃飯,后來(lái)那個(gè)牛排館也成為每次 TCO 比賽我們中國(guó)選手的主要聚會(huì)地點(diǎn)。
TCCC2007 的小組賽還比較順利,我輕松擊敗了 gawry , Per , marek.cygan 獲得小組第一挺進(jìn)決賽。可是決賽中,我為了提高速度以超過(guò) Petr ,再加上有些緊張,最后 500 分和 1000 分兩題又都掛了,落到了第 5 名。 TCCC2007 地點(diǎn)設(shè)在了奧蘭多,比賽結(jié)束后我們到附近的 Disney Land 去玩,那里的驚險(xiǎn)游戲比國(guó)內(nèi)刺激得多,有些遠(yuǎn)遠(yuǎn)超過(guò)我的極限,我們一行人一直玩到深夜才返回。許多選手還一起到奧蘭多魔術(shù)隊(duì)主場(chǎng)觀看了 NBA 現(xiàn)場(chǎng)比賽,可惜最后一節(jié)成為了垃圾時(shí)間。
TCO2008 我也依靠飄逸的 1000 分題中 800+ 分的提交闖入決賽。決賽前我還和 visualage 聊天,夸耀自己從來(lái)沒(méi)有所有題目全掛,更沒(méi)有拿過(guò)負(fù)分。可是在隨后的決賽中,這兩個(gè) “ 夢(mèng)想 ” 就都實(shí)現(xiàn)了, PE 對(duì)我的評(píng)價(jià)是太緊張了。基本每次 TopCoder 現(xiàn)場(chǎng)比賽都能見(jiàn)到 PE ,誰(shuí)知他每次懷疑我某些題目的正確性的時(shí)候,我的程序就一定是錯(cuò)的,如果下次我參加決賽,您就不要再看我程序了吧(呵呵,開(kāi)個(gè)玩笑)。
不過(guò)在決賽 Challenge 階段的最后時(shí)刻,我從第一視角目睹了 Petr 和 Tomek 的巔峰對(duì)決。在還有 15 秒鐘結(jié)束時(shí) Petr 還落后 Tomek 大概 30 分左右, Petr 成功 Challenge 了一個(gè)超過(guò)了 Tomek ,但是 Tomek 利用短短的 10 秒鐘也提交了一個(gè)成功 Challenge 又超了回來(lái),誰(shuí)知 Petr 得到這個(gè)信息之后又提交了一個(gè) Challenge ,可是運(yùn)氣稍差,如果那個(gè)數(shù)據(jù)用來(lái) Challenge 我的程序的話(huà), Petr 就能夠在最后 1 秒再次奪回冠軍的位置。能夠到最后一秒還能有機(jī)會(huì)成功翻盤(pán)的一定是神一般的人物,能夠把神一般的人物逼到最后一秒的也一定是神一般的人物,兩個(gè)神一般的人物你來(lái)我往,為大家上演了一場(chǎng)精彩的比賽。
歐洲獨(dú)霸:
又一次引用黃金雄教授在杭州 2008 時(shí)說(shuō)的話(huà), ACM 總決賽的實(shí)力分布由原先的美洲獨(dú)霸逐漸轉(zhuǎn)向了現(xiàn)在的亞歐爭(zhēng)霸。但是,我根據(jù)這些年的比賽結(jié)果發(fā)現(xiàn),從 2006 年開(kāi)始,團(tuán)體比賽和個(gè)人比賽,特別是個(gè)人比賽,歐洲選手一直保持著絕對(duì)的霸主地位,亞歐爭(zhēng)霸的說(shuō)法實(shí)在有些牽強(qiáng)。
從 2005 年開(kāi)始,幾乎所有三大賽事的冠軍都是歐洲選手。成績(jī)最好的要數(shù)俄羅斯,俄羅斯選手以 Petr , andrewzta 等為代表。俄羅斯選手訓(xùn)練刻苦,編程能力極強(qiáng)。歐洲的另一霸主就是波蘭,波蘭選手具有很強(qiáng)的靈氣,以 tomek , marek 以及 Eryx 為代表,程序設(shè)計(jì)在他們手中體現(xiàn)出了藝術(shù)氣息。
前幾天我也看到關(guān)于取消 NOIP 保送 資格的文章,我沒(méi)有發(fā)表評(píng)論,因?yàn)槲覜](méi)有看懂,為什么文章里把保送和保送資格混為一談,讓人覺(jué)得哭笑不得。這里我對(duì) 保送 資格還是想法不多,不過(guò)想比較一下我們中國(guó)選手與歐洲選手思維能力上的差別。
在高中時(shí),吳文虎老師就常說(shuō)中國(guó)選手的 IOI 成績(jī)很優(yōu)秀,的確這幾年從 IOI 成績(jī)上看,中國(guó)是絕對(duì)的霸主。可是 ACM-ICPC 的成績(jī),俄羅斯和波蘭等強(qiáng)隊(duì)的成績(jī)卻遠(yuǎn)在中國(guó)之上。于是我們總結(jié)的原因是:歐洲選手的編程能力強(qiáng)。我非常同意這個(gè)說(shuō)法。
但是 “ 歐洲選手的編程能力強(qiáng) ” 的說(shuō)法并不說(shuō)明他們的算法能力弱,相反他們的思維素質(zhì)非常高,他們具有非常正統(tǒng)和嚴(yán)密的思維方式,體現(xiàn)出經(jīng)過(guò)長(zhǎng)期訓(xùn)練的思維能力和素質(zhì)。
我覺(jué)得中國(guó)的 “ 高手 ” 和許多通過(guò)高考進(jìn)入名校的 “ 神人 ” ,在大學(xué)之前接受的教育都是以選拔為目的的,并沒(méi)有太多針對(duì)思維方式和能力的訓(xùn)練。記得小學(xué)要考重點(diǎn)初中,初中則拼搏重點(diǎn)高中,高中期間則夢(mèng)想名牌大學(xué),而在學(xué)習(xí)期間,我們并沒(méi)有太多機(jī)會(huì)訓(xùn)練自己的思維能力,至少在我的中學(xué)階段是這樣的。雖然很多高中已經(jīng)竭盡全力通過(guò)類(lèi)似研究性學(xué)習(xí)的方法鍛煉我們的創(chuàng)新能力,但是仍然不能改變選拔性考試 “ 高考 ” 這一事實(shí)。而在與西方選手交流的過(guò)程中,我覺(jué)得許多思維能力優(yōu)秀的學(xué)生很早就有機(jī)會(huì)接受系統(tǒng)的思維能力訓(xùn)練,尋找最適合自己的思考方法。我一次有機(jī)會(huì)看 Eryx 留下的草稿,發(fā)現(xiàn)他考慮問(wèn)題有非常嚴(yán)密的過(guò)程,從理解題目到想出算法每步都有根有據(jù),并不是隨機(jī)碰撞的結(jié)果。
現(xiàn)在歐洲選手與我們相比,思維能力上也并沒(méi)有劣勢(shì)。我有幸在投身 OI 競(jìng)賽之后,得到許多機(jī)會(huì)與其它選手交流,學(xué)習(xí)他們的思考方法,努力鍛煉自己這方面的能力,試圖與眾多歐洲選手對(duì)抗。
Mountain View?登頂:
GCJ2008 在 Google 總部 Mountain View 舉行,賽前我想用 Ying 的一句話(huà)來(lái)表達(dá)我對(duì)比賽奪冠的渴望, “ 我雖然獲過(guò)很多獎(jiǎng),但是缺少一個(gè)世界冠軍 ” 。早在 GCJ2006 ,我就擁有機(jī)會(huì)獲得冠軍,但是在失去那次機(jī)會(huì)之后一等就是整整的兩年。
比賽開(kāi)始不久, bmerry 的強(qiáng)勢(shì)起跑使我逐漸失去了奪冠的念頭,只得一心做好眼前的題目。 bmerry 在不到 2 個(gè)小時(shí)的時(shí)間里就做出了除了 C- Hard 以外的所有題目,他只要在最后一小時(shí)做出 C- Hard ,就基本上可以鎖定冠軍了。
不過(guò)我克服開(kāi)場(chǎng)的不順利之后,磕磕碰碰地在 2 小時(shí)過(guò) 5 分順利通過(guò)了 E-Easy 和 E-Hard 。擺在我面前的只有 B-Hard 和 C-Hard 。 B 題和 C 題相比之下, B 題我已經(jīng)有了一定的想法,可是 C 則是完全沒(méi)有想法。于是我決定先做 B , GCJ2008 的 B 題簡(jiǎn)直是我的克星,我先后用了 100 分鐘時(shí)間做這題都沒(méi)有結(jié)果,可以說(shuō)當(dāng)時(shí)狀態(tài)很差。大概到了 2:40 的時(shí)候,我查看 board 時(shí)突然發(fā)現(xiàn)了一件令人窒息的事情, bmerry 已經(jīng)嘗試了 C-Hard 并且超時(shí)了。由于 C-Hard 的分?jǐn)?shù)略高于 B-Hard ,我最后想要超過(guò) bmerry 就必須做出 C-Hard 。果斷放棄 B-Hard 之后,并沒(méi)有想出 C-Hard 的方法,寫(xiě)了一個(gè)搜索程序但是心里很沒(méi)底, Hard 數(shù)據(jù)的提交時(shí)限是 8 分鐘,于是到了 2 小時(shí) 52 分的時(shí)候,我毅然打開(kāi) C-Hard ,用搜索的程序運(yùn)行 C-Hard ,在焦急的等待之后,程序在運(yùn)行了 1 分多鐘以后神奇地運(yùn)行結(jié)束了。我依靠搜索方法通過(guò)了 C-Hard ,一舉超過(guò)了 bmerry 。 1 分鐘后 zhuzeyuan 也做出了同樣的題目,超過(guò)了 bmerry ,由于罰時(shí)排在第 2 名。我和 zhuzeyuan 還有 bmerry 比賽過(guò)程中都有不小的失誤,我很有幸把失誤的損失降到了最低點(diǎn),終于獲得了第一個(gè)世界比賽的冠軍。
這次 GCJ 的題目有非常詳細(xì)的解答,可以在比賽的鏈接里找到。 GCJ2008 的比賽結(jié)果從一定意義上,打破了歐洲選手多年的獨(dú)霸場(chǎng)面。加上原籍南非的 bmerry ,前五名中都沒(méi)有出現(xiàn)歐洲選手的名字,這也是在多年現(xiàn)場(chǎng)比賽中沒(méi)有出現(xiàn)過(guò)的。
這一年,我很高興看到 OI 選手中出現(xiàn)了 ahyangyi , yuhch123 , Loner 等各方面都極為出色的新人,真心希望你們能夠早日適應(yīng)大學(xué)的學(xué)習(xí)生活,再創(chuàng)佳績(jī)。
眾多新人的加盟,大大提高了清華 ACM 團(tuán)隊(duì)的實(shí)力。在 2008 年,清華大學(xué) ACM 隊(duì)創(chuàng)紀(jì)錄地獲得了 4 個(gè)分區(qū)賽的冠軍。明天最后一篇回憶中將分享 ACM-2008 中發(fā)生的趣事。
利用假期空閑之時(shí),將這幾年 GCJ , ACM , TopCoder 參加的一些重要比賽作個(gè)回顧。最后是 2008 年的杭州復(fù)出。
2008 年 ACM-ICPC —— 杭州復(fù)出
2006 年 ACM-ICPC 總決賽結(jié)束后, Mobile Robot 就宣布解散了,也許唯一的遺憾就是沒(méi)能獲得一個(gè)真正的世界冠軍。宣布退役 ACM 之后,我并沒(méi)有完全與 ACM 絕緣,每次 TopCoder 大賽之前還常常做一些 ACM 比賽調(diào)整狀態(tài)。記得 08 年初,我也全程觀看了總決賽,不過(guò)沒(méi)有想過(guò)復(fù)出。
杭州復(fù)出:?
一切事情要從一個(gè) zhuzeyuan 的電話(huà)說(shuō)起,時(shí)間是 11 月 8 日 晚上 10 點(diǎn)左右,當(dāng)時(shí)我正在參加 UVA 在線比賽而為 GCJ2008 作準(zhǔn)備。 zhuzeyuan 在電話(huà)里首先告知我 Loner 車(chē)禍的事情,好在現(xiàn)在 Loner 已經(jīng)痊愈了,當(dāng)時(shí)確實(shí)很擔(dān)心。隨后, zhuzeyuan 向我介紹了 2008 年 ACM 比賽的進(jìn)行情況,當(dāng)時(shí)北京和哈爾濱賽區(qū)已經(jīng)結(jié)束。然后,邀請(qǐng)我加入 Proxima 參加杭州賽區(qū)的比賽。我想當(dāng)時(shí)答應(yīng)的原因主要有 3 個(gè):?
(1) 我個(gè)人很喜歡 Coding ,雖然退出 ACM 已經(jīng)快兩年了,但是還經(jīng)常參加個(gè)人比賽。剛剛結(jié)束的 GCJ2008 中國(guó)區(qū)半決賽,出人意料的奪冠增強(qiáng)了我的信心。另外, ACM 這樣長(zhǎng)達(dá) 5 個(gè)小時(shí)的團(tuán)隊(duì)比賽造就了很特別的環(huán)境,賽場(chǎng)上的氣氛和激情是做裁判教練或者參加個(gè)人比賽中無(wú)法體會(huì)到的。?
(2) 3 年前的 2005 ACM 杭州賽區(qū),我留下了我大學(xué)生活中的一大遺憾。對(duì)于杭州 2005 的慘敗,我一直想尋找機(jī)會(huì)從那個(gè)跌倒的地方爬起來(lái),徹底擺脫紫金港校區(qū)留下的陰影。?
(3) 其實(shí)還有一個(gè)原因就是我家在杭州,而且在本科期間我也曾經(jīng)到杭州電子科技大學(xué)做過(guò)關(guān)于 ACM 的報(bào)告, lcy 老師的熱情給我留下了深刻的印象。?
對(duì)于 Loner 的車(chē)禍,我也覺(jué)得非常意外。這也是對(duì)于我們常年在校園騎自行車(chē)?yán)餀M沖直撞的警示。 Loner 現(xiàn)在能夠恢復(fù)得這么好,我們都很高興,祝你明年 ACM 好運(yùn)。?
加入 Proxima 的手續(xù)很順利,教練鄔老師對(duì)我復(fù)出想法的回答簡(jiǎn)單扼要:研一學(xué)生可以參加 ACM 比賽。?
Proxima 的另外兩名隊(duì)友分別是 zhuzeyuan 和 zhouyuan (周源),我加入 Proxima 之后,新 Proxima 先后進(jìn)行了 3 次訓(xùn)練比賽,隨后就出發(fā)到杭州電子科技大學(xué)參加 2008 年 ACM 杭州賽區(qū)的比賽了。?
當(dāng)時(shí),我通過(guò)許多網(wǎng)上資料和 zhuzeyuan 的描述了解了當(dāng)時(shí)清華的戰(zhàn)績(jī)。到杭州賽區(qū)之前,清華的 What ’ s Up 和 IronGods 已經(jīng)分別獲得了哈爾濱和北京賽區(qū)的冠軍。其中 IronGods 還獲得了哈爾濱賽區(qū)的亞軍, What ’ s Up 則一起來(lái)到杭州參加比賽。 Proxima 在杭州賽區(qū)之前已經(jīng)參加了北京賽區(qū)的比賽,成績(jī)是第二名。就當(dāng)時(shí)的形勢(shì)講,我們沒(méi)有資格考慮太多事情,如果想保留懸念就必須獲得杭州賽區(qū)的冠軍。
杭州賽區(qū)現(xiàn)場(chǎng)賽:?
在杭州賽區(qū)練習(xí)賽那天的上午,我們抓緊一切時(shí)間進(jìn)行了模擬訓(xùn)練,選擇的題目是 NEERC 的題目。題目難度有些大,我們做滿(mǎn)整整 5 小時(shí),直到 12 點(diǎn) 50 才急忙去吃午飯。結(jié)果很晚才到達(dá)比賽場(chǎng)地,到時(shí)候練習(xí)賽已經(jīng)開(kāi)始很久了。希望我們的遲到?jīng)]有影響旁邊隊(duì)熟悉比賽壞境。?
杭電賽場(chǎng)的環(huán)境很好,在賽場(chǎng)里我找回了 2006 年上海賽區(qū)的感覺(jué)。隊(duì)伍之間的空間很寬敞,電腦桌也很大,足以讓 3 個(gè)人在上面一起推導(dǎo)公式。馬上就見(jiàn)到了 lcy 老師,不過(guò)他帶來(lái)了一個(gè)不太好的消息 —— 不允許自帶鍵盤(pán)。好在杭電提供的鍵盤(pán)很標(biāo)準(zhǔn),對(duì)我們影響不大。?
正式比賽在第二天早上 9 點(diǎn)開(kāi)始,回顧一下比賽的過(guò)程吧:?
在 Proxima 隊(duì)中,比賽開(kāi)始時(shí),仍然由我準(zhǔn)備編程環(huán)境,然后從中間開(kāi)始讀題。我馬上發(fā)現(xiàn)了 D 是一道看似簡(jiǎn)單的題目,并且也注意到了這句話(huà):
WARNING: a naive algorithm might not be sufficient to solve this problem.
但是沒(méi)有想到的是 BFS 算法也算是 naive algorithm ,我交出了全場(chǎng)第一個(gè)提交,結(jié)果是理所當(dāng)然的 TLE 。不過(guò)那句 WARNING 稍微有些飄逸。
zhuzeyuan 發(fā)現(xiàn) A 是簡(jiǎn)單題目,于是我馬上寫(xiě) A 。
19?分鐘,?A?:判斷兩張圖的修改距離。枚舉全排列,統(tǒng)計(jì)即可。
A 是最簡(jiǎn)單的題目,由于開(kāi)始 D 的耽擱,我們大概是全場(chǎng)第 4 個(gè)出題的隊(duì)伍。
接著, zhouyuan 發(fā)現(xiàn) J 也很簡(jiǎn)單,于是我轉(zhuǎn)向 J 。
28?分鐘,?J?:允許刪點(diǎn)的并查集問(wèn)題。通過(guò)添加新點(diǎn)的方法實(shí)現(xiàn)刪點(diǎn)。
過(guò)了 J 之后,排名暫時(shí)上升到第一位。隨后, zhuzeyuan 發(fā)現(xiàn)沒(méi)有新題可寫(xiě),于是就開(kāi)始寫(xiě) C ,過(guò)程中,我和 zhouyuan 發(fā)現(xiàn) G 比較簡(jiǎn)單,于是插空寫(xiě) G 。
50?分鐘,?G?:簡(jiǎn)單圖論問(wèn)題。開(kāi)始刪點(diǎn)判斷錯(cuò)誤造成?WA?了一次。
59?分鐘,?C?:高精度計(jì)算和素?cái)?shù)判定問(wèn)題。這題是?zhuzeyuan?寫(xiě)的。
不到一個(gè)小時(shí)就通過(guò)了 4 題, Proxima 獲得了一個(gè)很好的開(kāi)局。對(duì)于杭州賽區(qū)難度的題目,能夠在第一個(gè)小時(shí)通過(guò) 4 題已經(jīng)很順利了。對(duì)于許多分區(qū)賽中會(huì)出現(xiàn)更多的簡(jiǎn)單題目的情況,有時(shí)能夠做到一小時(shí) 5 題。但是一小時(shí) 6 題實(shí)在太難了,記得我們?cè)谝淮斡?xùn)練比賽中做到了一小時(shí) 6 題,已經(jīng)是我們的能力極限了。
接下來(lái)我實(shí)現(xiàn)了一下 B ,可是由于發(fā)生了理解錯(cuò)誤,計(jì)算結(jié)果與題目要求計(jì)算的結(jié)果直接存在重復(fù)排列問(wèn)題,只好把程序放在一邊。
隨后, zhuzeyuan 開(kāi)始實(shí)現(xiàn) H ,提交之后我開(kāi)始寫(xiě) F 。
95?分鐘,?H?:計(jì)算幾何,如果使用?O(n2)?的算法需要注意常數(shù)不易太大。
105?分鐘,?F?:自動(dòng)機(jī)判斷相等問(wèn)題,通過(guò)計(jì)算差乘的方法能夠在?O(n2*|Sigma|)?內(nèi)解決
H 的提交等了很久, H 的 Yes 出來(lái)后不久我就寫(xiě)完了 F ,提交之后也 Yes 了。大概在 2 個(gè)小時(shí)左右我們做出了 6 題,其實(shí)如果不在 B 上浪費(fèi)時(shí)間能夠更早一些。在 2008 杭州賽區(qū),我們又一次獲得了 6-4 的領(lǐng)先優(yōu)勢(shì)。
下面我們面臨一個(gè)比較困難的狀況, E 和 I 看似都比較復(fù)雜,但明白題意的 B 和 D 都沒(méi)有想出算法。 2008 年杭州賽區(qū)的題目中,基本沒(méi)有中等難度的題目,所以我們通過(guò) 6 題之后就直接進(jìn)入了比賽后期。當(dāng)時(shí)我們分了一下工,我決定死磕 D 題, zhouyuan 負(fù)責(zé)推 B 題的公式。 zhuzeyuan 嘗試新題目 E 或者 I 。
我的工作進(jìn)行很不順利,先實(shí)現(xiàn)了一個(gè)普通的 A* 算法,由于優(yōu)化得不好還是 TLE 。現(xiàn)在回想起來(lái), D 題標(biāo)準(zhǔn) A* 算法中使用的那個(gè)優(yōu)化還是挺巧妙的,至少很有藝術(shù)感。我放棄 A* 算法之后, zhouyuan 似乎已經(jīng)推好了 B 題的公式,開(kāi)始幫助我實(shí)現(xiàn) D 題。
163?分鐘,?D?:狀態(tài)最短路徑問(wèn)題,通過(guò)?A*?算法加一些優(yōu)化可以輕松通過(guò)。
zhouyuan 提出了一個(gè)很重要的優(yōu)化方法,先通過(guò)解方程的方法判斷是否有解,在確認(rèn)有解的情況下使用雙向廣度優(yōu)先搜索,程序?qū)懞弥笥?TLE 了。不過(guò)我覺(jué)得運(yùn)行時(shí)間已經(jīng)差不多了。于是,我使用了卡節(jié)點(diǎn)的方法,終于在第 5 次提交通過(guò)了 D 。 D 題我們用了大概一個(gè)小時(shí)左右。這時(shí) What ’ s Up 早已通過(guò) 5 題,不過(guò)由于他們卡在 H 題上,我們?nèi)匀灰?7-5 領(lǐng)先。
zhuzeyuan 確認(rèn) E 和 I 比較復(fù)雜之后,我們開(kāi)始合攻 B 題。 zhouyuan 其實(shí)受到了我原先錯(cuò)誤算法的誤導(dǎo),他得到一些公式來(lái)計(jì)算繁衍函數(shù),通過(guò)繁衍以及原先程序的結(jié)果得到正確結(jié)果。不過(guò),從當(dāng)時(shí)的形式看,這樣也是很不錯(cuò)的選擇。
程序很快就寫(xiě)好了,提交之后又是奇怪的 TLE 。 B 題的 TLE 和 D 的 TLE 本質(zhì)完全不同, B 題我們算法的復(fù)雜度是 O(n4) 的,對(duì)于 n<=20 的數(shù)據(jù)范圍,時(shí)間上應(yīng)該沒(méi)有問(wèn)題。于是,我生成了 100 組測(cè)試數(shù)據(jù),發(fā)現(xiàn)總共只需要 1 秒左右。
在 B 題的這一點(diǎn)上,我覺(jué)得命題人做的很不合理,雖然此題存在 O(n3) 的算法,但是既然把范圍出到 20 ,就應(yīng)該允許 O(n4) 的算法通過(guò)。可是命題人一共疊出了 6000 組測(cè)試數(shù)據(jù),使得我們的程序超時(shí)了。而且在 Clarify 中的回答是 1000 多組,我們優(yōu)化程序之后還是一直 TLE ,當(dāng)時(shí)我們?cè)趺磿?huì)想到是 6000 多。至少這里的范圍 20 極具誤導(dǎo)性。幸好, zhuzeyuan 及時(shí)想出了一個(gè)解決方法 —— 打表。由于對(duì)程序沒(méi)有信心,打表的 15 分鐘時(shí)間內(nèi)我們 3 人都只得通過(guò)手工計(jì)算簡(jiǎn)單數(shù)據(jù)來(lái)確認(rèn)程序的正確性。
236?分鐘,?B?:比較復(fù)雜的動(dòng)態(tài)規(guī)劃,需要考慮?4?種情況。
打完表之后提交終于得到了第 8 個(gè) Yes ,時(shí)間是 236 分鐘,距離封版只有 4 分鐘。由于 6000 組的陰險(xiǎn)數(shù)據(jù),我們從第一次提交 B 題到通過(guò) B 整整用了 50 分鐘,而且是 3 個(gè)人一直在一起做。
封版時(shí),我們?nèi)员3至?8-6 的領(lǐng)先優(yōu)勢(shì)。但是接下來(lái),我們犯下了杭州 2008 最大的錯(cuò)誤,如果類(lèi)似的錯(cuò)誤在總決賽中出現(xiàn),我們將很可能失去領(lǐng)先位置。當(dāng)時(shí)我們沒(méi)有看到港大掛起 E 的氣球,于是在 E 和 I 中選擇了 I ,結(jié)果深深地陷在了 I 的無(wú)底洞中,直到結(jié)束都不能自拔。
I?:模擬題,需要考慮的情況比較多。
E?:計(jì)算幾何。計(jì)算半平面的交。
現(xiàn)在回想起來(lái), E 題的難度遠(yuǎn)沒(méi)有 I 題大,我們錯(cuò)誤估計(jì)了 I 的難度。非常敬佩賽場(chǎng)上通過(guò) E 題的港大和 I 題的湖南大學(xué),你們不愧為射雕英雄。
清華?2008?戰(zhàn)況:
2008 年,清華延續(xù)自己在 ACM 大陸賽區(qū)中的霸主地位, 4 支不同的隊(duì)伍獲得了創(chuàng)紀(jì)錄的 4 個(gè)不同賽區(qū)的冠軍。分別是:
1. What ’ s Up —— 哈爾濱賽區(qū)冠軍
2. IronGods —— 北京賽區(qū)冠軍
3. Proxima —— 杭州賽區(qū)冠軍
4. ZCS —— 成都賽區(qū)冠軍
從 ACM 的規(guī)則上講 4 支隊(duì)伍都獲得了進(jìn)軍總決賽的資格,清華總決賽隊(duì)伍的選拔過(guò)程在成都賽區(qū)結(jié)束的第二天就開(kāi)始了。
從我的角度描述另 3 支隊(duì)伍的情況吧:
What ’ s Up 是清華第一個(gè)獲得冠軍的隊(duì)伍,杭州賽區(qū)的過(guò)程中,他們以 amber 主寫(xiě)程序的模式進(jìn)行,在比賽開(kāi)始階段體現(xiàn)出了很強(qiáng)的沖擊力,不過(guò)卡住 H 后的慌亂略顯出組隊(duì)模式的缺陷。雖然他們?cè)诤贾葙悈^(qū)之后就選擇放棄了總決賽資格的爭(zhēng)奪,但是我們都深知他們的實(shí)力。后來(lái) What ’ s Up 的成員擔(dān)任了 PK 比賽的裁判工作。
ZCS 由剛進(jìn)入清華學(xué)習(xí)的三名大一學(xué)生組成,成員是 yuhch123 , Cheryl 和 ScaleRhyme 。我參加 Proxima 之后沒(méi)有和 ZCS 交過(guò)手,不過(guò)在 Ural 和 SGU 上比賽時(shí)看到過(guò) ZCS 的身影。在杭州賽區(qū)之后, ZCS 在成都賽區(qū)創(chuàng)造了 7/7(7 提交 7 通過(guò) ) 奇跡,不過(guò)和北京賽區(qū)相似的是后期略顯經(jīng)驗(yàn)不足。隨后, ZCS 沒(méi)有參加校內(nèi) PK 賽。
IronGods 的組成是 OpenGL , ahyangyi 和 ghy 。在 IronGods 成立之初,我一直很看好這支隊(duì)伍。哈爾濱賽區(qū)結(jié)束后,記得 ahyangyi 還來(lái)和我抱怨比賽中的失誤,那道高精度題目確實(shí)有些過(guò)于復(fù)雜(呵呵,不過(guò)至少數(shù)據(jù)沒(méi)有錯(cuò)誤)。北京賽區(qū)的情況,我是事后聽(tīng) dzx 介紹的, IronGods 依靠最后一小時(shí)的穩(wěn)定發(fā)揮,通過(guò) 3 題,一舉壓倒 Proxima , Carriage 和 ZCS 獲得冠軍。可是幾天后,我驚奇的發(fā)現(xiàn)自己需要面對(duì)強(qiáng)大的 IronGods 了。
IronGods 的組合與新 Proxima 驚人得相似, IronGods 的 OpenGL 與 ahyangyi 還有我和 zhuzeyuan 都是 TopCoder 上的 Target (中國(guó)一共有 7 個(gè) Target ,另外 3 個(gè)是前輩 haha , lympanda 和 ZCS 隊(duì)中的 yuhch123 ,看好 zhoujie 成為第 8 個(gè),加油呀!),他們的編程能力與我和 zhuzeyuan 不相上下。從 TopCoder 的成績(jī)上看,我們兩人的速度略快。
另一名隊(duì)員 ghy 和 zhouyuan 都很擅長(zhǎng)思考算法, ghy 結(jié)束 OI 時(shí)間比較短,狀態(tài)保持得很好, zhouyuan 對(duì)于深入的算法了解比較扎實(shí)(北京的 A 很贊呀!)。
從配合上說(shuō), IronGods 組隊(duì)時(shí)間長(zhǎng),配合方面比我們默契許多。我們重組后雖然也進(jìn)行了一些訓(xùn)練,不過(guò)在比賽中普遍交流偏少,特別是我和 zhouyuan 的交流,在后幾場(chǎng)比賽中才有些成功的配合。
不過(guò)從穩(wěn)定性角度看,我們稍占上風(fēng), TopCoder 上的 Volatility 值至少可以說(shuō)明一些。而且 ACM 比賽時(shí)間長(zhǎng)達(dá) 5 小時(shí),穩(wěn)定性的要求應(yīng)該比 TopCoder 還高一些。
清華校內(nèi)?PK?:
后來(lái), zhuzeyuan 代表 Proxima 與 IronGods 協(xié)商之后,大家決定采用三局兩勝的賽制,并定下了 3 場(chǎng)比賽的時(shí)間和題目安排。
關(guān)于總決賽隊(duì)伍的選拔,我個(gè)人非常不贊成直接指定,可能與我的一些經(jīng)歷有關(guān)吧。已經(jīng)進(jìn)入研究生學(xué)習(xí)的我,對(duì)參加總決賽已經(jīng)沒(méi)有兩三年前的激情了。不過(guò)我個(gè)人的觀點(diǎn)是,如果學(xué)校指定,我對(duì)于 4 種結(jié)果都可以接受;如果進(jìn)行 PK 選拔,賽場(chǎng)上我一定拼盡全力。
兩場(chǎng) PK 過(guò)程中,我們都在 bbs.pku 上發(fā)布了現(xiàn)場(chǎng)的即時(shí)排名情況。由于清華 ACM 團(tuán)隊(duì)有嚴(yán)格規(guī)定要求對(duì)兩次 PK 中使用的題目保密,我這里就只留下了比賽的大致過(guò)程。
第一場(chǎng) PK ,時(shí)間和吉隆坡賽區(qū)完全相同,過(guò)程大致如下:
Proxima 啟動(dòng)比較快,到 2 小時(shí)左右就獲得了 5:2 的領(lǐng)先優(yōu)勢(shì)。
題 F 是這場(chǎng)比賽中我們最大的失誤, F 浪費(fèi)了很多時(shí)間,而且最后都沒(méi)有過(guò)。
IronGods 利用 Proxima 卡住 F 的時(shí)機(jī)連追 4 題,以 6:5 反超。
發(fā)現(xiàn) IronGods 反超之后,我又嘗試了幾次 F 題,但還是不能通過(guò)。比賽還有 70 分鐘結(jié)束,而且我們手上并沒(méi)有其他題目。 zhuzeyuan 在關(guān)鍵時(shí)候毅然決定開(kāi)始寫(xiě) J ,記得他說(shuō)的一句話(huà)是 “ 沒(méi)有時(shí)間了,我必須開(kāi)始寫(xiě)了 ” ,當(dāng)時(shí)形勢(shì)不容樂(lè)觀。好在 J 成功 1Y ,士氣大振。
Proxima 隨后連過(guò)兩題重新占據(jù) 7:6 優(yōu)勢(shì)。
最后, IronGods 追成 7:7 平,比賽又打得難解難分。
IronGods 最后時(shí)刻也還有機(jī)會(huì),我們又一次目睹了 IronGods 的絕地反擊實(shí)力,可能他們最后做 H 的選擇值得商榷。
第一場(chǎng) PK 過(guò)程中兩支隊(duì)都有明顯失誤的時(shí)期,我們由于失誤在中期,所以罰時(shí)較少。最后依靠罰時(shí)險(xiǎn)勝,在 PK 中占得先機(jī)。
第二場(chǎng) PK ,時(shí)間設(shè)在 12 月 25 日 的晚上進(jìn)行,題目編號(hào)從 A 到 L ,共有 12 題之多。第二場(chǎng) PK 比前一場(chǎng)進(jìn)行得更激烈,過(guò)程中兩支隊(duì)伍都長(zhǎng)時(shí)間保持了很好的狀態(tài),比賽過(guò)程中多次交換領(lǐng)先位置:
開(kāi)局 Proxima 起步略快, 65 分鐘就通過(guò)了 5 題 BDEFK 。
開(kāi)局看似順利,不過(guò)我們都明白:真真的比拼還沒(méi)有開(kāi)始。
Proxima 卡在了 H 和 C 上, IronGods 通過(guò)了 BCDFK 追成 5:5 平,罰時(shí) Proxima 領(lǐng)先。
IronGods 通過(guò)了 G ,首次反超 6:5 。
Proxima 經(jīng)過(guò) rejudge 通過(guò)了 H ,出現(xiàn)了 6:6 平,罰時(shí) Proxima 領(lǐng)先。
Proxima 第 10 次提交才通過(guò)了 C ,再次獲得題數(shù)領(lǐng)先 7 :6 。
如果輸?shù)袅诉@次 PK ,題 C 則是最大的敗筆。
IronGods 通過(guò)了 J ,追成 7:7 平, IronGods 在罰時(shí)上領(lǐng)先。
此時(shí)的罰時(shí)落后就是 Proxima 在 C 題上出錯(cuò) 9 次的惡果。
Proxima 第 4 次提交才通過(guò) G ,以 8:7 反超,但罰時(shí)還是很大。
IronGods 通過(guò)了 H ,又追成 8:8 平,利用罰時(shí) IronGods 再次獲得領(lǐng)先。
這已經(jīng)是第 6 次出現(xiàn)平分了。這時(shí)還不到 3 個(gè)小時(shí),校內(nèi) PK 賽的題目難度并不在 2008 杭州賽區(qū)的難度之下, 3 小時(shí)的 8:8 的高比分平局是現(xiàn)場(chǎng)比賽中很難看到的。而在高比分平局中罰時(shí)也是很重要的,此時(shí) IronGods 占據(jù)明顯的優(yōu)勢(shì)。
Proxima 經(jīng)過(guò) rejudge 通過(guò)了 I ,再次超出 9:8 。
Proxima 通過(guò)了 J ,優(yōu)勢(shì)擴(kuò)大到 10:8 。
記得題 J 的第一次提交開(kāi)始的返回結(jié)果是 “ Other-Contact Staff ” ,看到這個(gè)回復(fù)之后 zhuzeyuan 馬上跑到 Judge 室,在被工作人員擋住之后, zhuzeyuan 很奇怪地問(wèn)道 “ 難道不是你們讓我來(lái) Contact 的嗎? ” ,囧死了。不過(guò)很快就 rejudge 成 Yes 了,題 J 的通過(guò)也從一定意義上逆轉(zhuǎn)了罰時(shí)的不利, IronGods 如果想翻盤(pán)就必須在最后一小時(shí)重新上演北京賽區(qū)封版通過(guò) 3 題一幕。
Proxima 通過(guò)了 A ,優(yōu)勢(shì)擴(kuò)大到 11:8 。
記得最后提交 A 題的時(shí)候,我緊張得手都有些發(fā)抖了。當(dāng)時(shí)只剩下 25 分鐘, IronGods 還沒(méi)有開(kāi)始寫(xiě) A 和 L 兩題,所以在最后的時(shí)間里他們已經(jīng)不可能通過(guò)余下的 4 題了。 A 題的 Yes 也就成為了這場(chǎng) PK 的勝利宣言。
IronGods 最后時(shí)刻通過(guò)了 I ,最終題數(shù)為 11:9 。
此次校內(nèi) PK 的激烈程度決不亞于 2006 年上海賽區(qū),能夠最終贏得這場(chǎng) PK 使得我們更有自信地站在總決賽的現(xiàn)場(chǎng)。
首先感謝關(guān)心我們的同學(xué),記得第一場(chǎng) PK 當(dāng)天正在舉行吉隆坡賽區(qū)比賽, bbs.pku 上還是出現(xiàn)了如此多的帖子為我們雙方加油。第二場(chǎng) PK 結(jié)束時(shí)已經(jīng)是晚上 11 點(diǎn),我們手機(jī)還不斷收到祝賀短信。
向 IronGods 三位天王致敬,在 PK 過(guò)程中只需略微的變化,出現(xiàn)在斯德哥爾摩的就很可能是你們。棋逢對(duì)手是我 ACM 生涯的一大幸事,相信你們明年一定能夠做得更好。
我想這是清華第一次使用公開(kāi)的現(xiàn)場(chǎng) PK 方式來(lái)選拔總決賽隊(duì)伍,個(gè)人覺(jué)得 PK 的方式除了公平之外還有許多優(yōu)點(diǎn)。首先, PK 方式可以使得各隊(duì)伍能夠更從容地選擇和準(zhǔn)備不同的分區(qū)賽賽區(qū),有效提高學(xué)校的總體成績(jī)。其次,通過(guò) PK 的過(guò)程,可以加強(qiáng)各隊(duì)之間的交流,隊(duì)伍各方面水平能夠得到全面提高。真是一舉兩得。
利用假期空閑之時(shí),將這幾年 GCJ , ACM , TopCoder 參加的一些重要比賽作個(gè)回顧,包括今天一共 10 篇。接下來(lái)的重要比賽就是世界總決賽了,縱觀世界總決賽各隊(duì),雖然形勢(shì)不容樂(lè)觀,但我們一定會(huì)拼盡全力。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的ACRush 楼天城回忆录的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 如何将二维数组作为函数的参数传递
- 下一篇: 最健康的睡眠时间究竟是多少?