1. 程式人生 > >十萬行程式碼——記我的ACM之路

十萬行程式碼——記我的ACM之路

記得有人說過,要想成為某個領域的精英就得花費一萬個小時;好像也有人說過,要想熟練的掌握某門程式語言就得寫十萬以上的程式碼。我算了一下,大學以來差不多總共寫過1500多個 .c/.cpp 檔案了吧,如果每個檔案的有66行程式碼的話,也差不多十萬行了吧,然鵝,我離大佬的差距好像還是很遠……

寫這篇文章呢,主要是要從實驗室滾蛋了,紀念一下。也想給還在ACM之路上徘徊的學弟學妹們一點點微不足道的個人經驗,還望大佬們勿笑。以下所談均為我個人意見,不代表ACM國際官方觀點~

先簡單回憶自己的ACM之路。記得初次接觸ACM是在大一下學期,因為C語言成績比較好,被兩位老師拉進實驗室。當時覺得自己和大佬們的差距很大,又不想面對,其實是有點不情願的,所以說啊,有差距不可怕,只要敢追趕就好。不過由於座位有限,到了大二上才算正式踏上我的ACM之路。一進實驗室,每天對著電腦只會做一下隊長佈置的每週要做的題,完全不知道該主動做些什麼,學些什麼知識。有時候甚至會為了在簽到表上籤個字而來實驗室待會,現在想來也確是可笑。

轉眼到了大二下學期,因為上學期末自己發生了一點不愉快的事情,為了讓自己不經常去想一些不愉快的事,我打算讓自己忙起來,忙起來就好了,然後開始慢慢的把泡在實驗室裡,然而,這時候我還是不是很明白我想要的是什麼,我該做些什麼。直到去年省賽老師宣佈我作為一名隊員參賽的那一瞬間,其實當時只是單純的不想給兩個隊友拖後腿,然後那段時候瘋狂的學習,每天幾乎都在實驗室,很晚才回宿舍。感覺那是我學到新知識最多最密集的一段時間。

到了省賽,做了3道題,第4題一直想不明白,後來知道是沒搞懂題意。出來的時候內心非常忐忑,因為3道題想要得牌是非常困難的。到了滾榜的時候,一開始還比較快,到了要揭示銅牌區的時候變得異常緩慢(應該是為了節目效果),而我們就在銅牌區的最後一名,如果鐵牌區的第一名在封榜後的一個小時內做出了題,那我們就涼了……然鵝,我們沒有那麼幸運,當時我還在心裡罵了一句:靠!這麼狗血的劇情不是隻會出現在狗血小說和電視劇中嗎……鐵牌區第一,真的諷刺,好像做夢……出去之後我們三個就一直沉默不語,遠離人群,就連大二的(當時大一)都拿牌了,真的無地自容,晚上大家很歡樂的玩狼人殺,但是我想我們三個心情一定特別複雜。

那段時間真的是做啥啥不順利,總想做點什麼證明我能行,但是總是被現實啪啪打臉。不過,我現在是很感激這次失敗的,我也是在那之後第一次明白了“只問耕耘,不問收穫”這句話的道理。如果那時候我僥倖得牌了,依我的性格很有可能飄飄然自滿,而不再踏踏實實的學演算法。可見有時候得牌也不見得是一件好事,反之不得牌也不一定就是件壞事。知恥而後勇就好。也是從那時起,我才知道自己如果努力一把是有能力得牌的,我也找到了我的目標——我想要那塊牌。

其實到了大三下學期,內心有點浮躁了,又是要忙著考研啥的,比起上學期,這個學期好像沒有學到太多的演算法知識。可惜了上一個寒假,果然說要假期學習什麼的都是不靠譜的……

好了,進入正題,來說下在ACM學習中我的一點經驗。我現在回想之所以剛進實驗室的時候無所適從就是因為不知道自己該學啥,進一步說就是學的東西不繫統,都是做題碰到什麼知識點然後去學。然鵝,學多了會發現好多知識點之前是有關係的,比如如果你學會了並查集,那麼克魯斯卡爾版的最小生成樹演算法就比較好實現了。所以我覺得大家可以照著某一本數書或者某個模板的知識點循序漸進的學習,我給大家推薦一下《ACM/ICPC程式設計系列》的書,有數論、圖論、組合數學、計算幾何等。裡面知識點部分講解的還可以,主要是還有相應的POJ等上面的題可以接著練一下。還有《挑戰程式設計競賽》這本書,上面的技巧很多,但是個人感覺有點晦澀,待有一定基礎的時候再看也好。

大家都知道,演算法學習其實是比較枯燥的一件事情,因為學習過程中經常會遇到瓶頸,但是對於比較難的知識點和題目不能總去躲避,還是要硬著頭皮上,這樣才能有提高。我覺得演算法學習(包括看題解)都有以下由優到次的級別:看別人的思路,自己實現 -> 讀別人的程式碼,然後自己不參考任何東西敲出 –> 先比著敲一遍,然後再慢慢去理解。如果你什麼時候能不參考任何東西把程式碼準確無誤的寫出來了,我覺得你就是真的掌握了。

除了演算法知識的學習,刷題也很關鍵,你會發現題目做多了,一些題自然就有思路了,正所謂熟能生巧吧。但是我極其反對太過依賴於題解,還是要獨立思考,就算你的思路會超時,也要想方設法去優化,去另尋他法,而不是一不會就去看題解。一般,做題的時候,我在理解題意的同時會分析一下時間複雜度,有時候甚至可以通過時間複雜度來判斷要用什麼演算法。如果是1000左右,基本暴力即可;如果是 1e5,最多應該是O(logn)的時間複雜度;如果再大點就要看優化或者找別的思路了;如果非常大,超過1e9,則很有可能是有公式或者有規律。

另外刷題也最好按照難度的遞增或者題目分類去刷,這裡給大家推薦 51nod 這個網站,可以從1級題開始刷起,很多題的解題方法都是很不錯的。還有著名的codeforces,不過我覺得這個題目不錯,但是類別太雜了,可以當作比賽打一下。還有一點我比較推薦的就是要寫部落格,因為有些題你看題解你可能覺得也就這麼回事,但是讓你自己做還是做不出來,但是如果你要寫部落格給別人寫明白就不一樣了,你一定會要求你自己徹底搞懂這道題。當然寫部落格會耗一點時間,也不是所有的題都要去寫出來。而是那些思路比較新穎,有點難度的題。如果寫就希望認真一點,不要說顯然……然後給出個結果……另,給程式碼加上必要的註釋也是很好的習慣。

還有就是可以模仿大佬們的程式碼風格,比如我之前定義長整數就會寫個 long long,但是後來知道可以 typedef long long LL; 然後就可以用LL代替了,方便了很多,又比如之前會寫n/2,現在會寫>>1,運用位運算也會讓程式執行的更快一點。偷偷告訴你們,好好把握身邊的大佬,有不懂的就去問,不要不好意思,你會受益的。

最後,說點有關ACM比賽的,ACM是三人賽,三個人榮辱與共,三個人的配合很重要,比賽時一定不要指責某位隊友而破壞三個人的心態,賽前也應該按照比賽的要求多磨合,鍛鍊三人間的配合度。當然,最重要的是不要辜負你隊友的期望,給隊伍拖後腿。

最後的最後希望還在ACM之路上前行的學弟學妹們能繼續加油,勝不驕敗不餒,來年賽出你們的水平,我最近也的確感受到了和大佬之間的差距,希望有機會可以把我薄弱的部分增強一下。好了,好了,滾去考研了,拜~