1. 程式人生 > >ACM新手入門掃盲

ACM新手入門掃盲

前言

本帖是給本校大一生寫的,致力於給有志於搞ACM-ICPC的同學一個瞭解概況的機會,是基本的入門掃盲帖子。詣在給出一個大局觀,給出一個可以努力的方向。以下純屬個人見解,若有謬誤,敬請指出。

關於ACM

ACM是一項非常難的競賽,需要大量的訓練時間,需要強大的抗壓能力,需要良好的團隊配合,需要足夠的天賦。以上四點除了最後一點以外都是可以用足量的時間來換取的,天賦可以讓你在天才之間的撕逼中脫穎而出,但大多數acmer都是大一開始接觸程式設計的,因而所能達到的高度主要取決於個人與團隊的努力。

ACM賽場上的目的是在儘量短的時間內過掉儘量多的題目。acmer需要關注的問題,一是怎麼寫可以過,二是怎麼寫最容易過,三是怎麼寫能在最短時間內過

。具體來說,一是要學習或找到可以解決問題的演算法,二是要選擇比較好的解決方式或者將問題轉化為較為容易解決的問題,三是找到一種程式碼量,除錯量較小的實現方法。

基礎入門

要搞acm最相關的基礎課程是《C/C++》《資料結構》《離散數學》。《C/C++》由於其效能優勢,是程式設計競賽的主流語言,Java Pascal次之,Python屬於後起之秀,正式的比賽一般支援C/C++/Java。《資料結構》《離散數學》是最基礎的知識需要掌握穩固。

關於入門的書籍學習語言我推薦《C++ Primer Plus》,C的話我不清楚,但我覺得《C Primer Plus》應該也是不錯的選擇。C/C++的基本寫法是C輸入輸出的C++或者純C。《資料結構》一般的教科書即可,差別不太大。《離散數學》可以選擇Roson第七版的,機械工業的,已經有中文的了。

競賽的入門書籍比較推薦《挑戰程式設計競賽》或者劉汝佳的《入門經典》,不推薦買本《演算法導論》防身。

國內著名OJ: poj zoj hdoj

著名線上比賽網站(均為提交程式碼開源):

  • cf 時間坑,俄羅斯網站
  • tc 需要配置本地客戶端,偏智商
  • bc 杭電辦的,國內友好,與上面兩個網站比有差距。
  • topcoder open, google code jam這些屬於年度賽事,難度很大。

成為一位強大的acmer

成為一位強大的acmer一是要看個人的實力,二要看團隊的實力。

個人的實力可以通過寫題,讀書,讀論文,讀blog,打比賽來提高。主要的衡量標準一是看題量,二是看網上競賽的rating,三是實際的比賽能力。

ACM是團體比賽,團隊能力更為重要(除非隊內有一人七題的杜教主)。團隊的實力可以通過組隊訓練,提升個人能力來提高,最好的做法是任何團體賽都是單機操作,真實模擬比賽環境,這個是SJTU真實的做法。團隊能力並非簡單進行max或者加和的操作,存在大量隊伍能夠以較低的相對rating戰勝rating相對高的,當然差距較大時基本不可能,合作以弱勝強的基礎是一定的個人實力。對於一個團隊而言最重要的是要用完整的技能樹以及相互協助的能力,可以在初期就分配好每個人主要攻克的方向,之後可以逐漸加深各個方向的覆蓋,最好保證每人會一些基礎的演算法,然後一個人的題其他人可以幫忙進行除錯或者提供思路。

有種說法說是選對賽區少奮鬥一年,選對隊友少奮鬥一輩子。選賽區很重要,賽場上萬事皆有可能發生,賽區拿牌或者出線難度也各不相同,賽區這個東西要看團隊的技能樹還有對手的能力,這個需要經驗以及強大的運氣支撐,在此不多進行討論。選隊友這個事情很重要,具體的標準,一要看基礎實力,二要看進步速度,三要看人品,四要看臉。前倆其實就是看能力,存在不少人可以一年超神,看出大神潛質就可以直接死死抱住大腿,共同進步。人品就是看對不對眼,存在一些人有一定水平但是處事讓人不舒服或者行為不好,因為要長期一起訓練,要慎重(當然大多數acmer都是正直,可愛,善良的宅男女)。假如你是萌妹子(萌漢子),找到一個強大的漢紙(妹紙)作為朋友(各種朋友),就可以被穩定帶飛了,有臉可以選擇男女通吃,相容幷包,走向人生巔峰。

中國屬於ACM的強國,按照cf中的rating通常而言三個低分小藍能打個銅,三個高分的小藍或者低分小紫可以打個銀,三個高分小紫或者低分橙名可以衝金,比較強的橙名或者是紅名組隊基本可以金牌衝出線,再向上基本就可以衝wf獎牌了。以上只是經驗結論,存在一些人rating較低但賽場上很強,也存在rating較高的人賽場上不行。

個人實力的提升

個人覺得個人實力主要是看編碼能力和演算法能力。

編碼能力:

  • 熟悉各類語言,掌握C/C++/Java的基本運用(庫函式)
  • 熟悉各種優化技巧,各種預處理,亂搞的方法,熟悉除錯
  • 良好的命名風格,程式碼風格,瞭解設計模式,面向物件

衡量的主要標準大概就是實現演算法的速度,寫模擬題的能力,還有對於卡常數題目的處理能力,訓練方式就是多寫題目,多看資料。另外一個方法看你的隊友是否能夠很舒服地除錯你的程式碼。風格我認為比較重要,因為acmer大多缺乏對於良好風格的追求,而寫出漂亮的程式碼對於除錯而言很重要,也能讓人理清邏輯。可以參照各類軟工書籍如《程式碼大全2》,《Head First Design Pattern》,可以取其中和編碼時間不衝突或者效益大過浪費的時間的。

演算法能力:

  • 掌握的演算法及知識的量,即廣度,涉獵面較廣可以從多方面看問題,更容易解決問題。
  • 掌握的深度,即做難題的能力,一些題目在思維上突破比演算法本身重要。
  • 數學能力,讓你能更好地分析問題,找到問題的關鍵或是直接利用公式獲得答案。
  • 腦洞,讓你能夠更好地改造,組合,運用演算法,讓你突破傳統演算法禁錮。

acm入了門之後大量的時間都是在學習數學。幾乎所有的計算機理論均是基於數學的,演算法大師也多是數學家,演算法論文裡也都是數學符號。要想搞好acm學習各種數學是不可避免的。當然計算機學科的數學和數學系的數學又有不同,一切都是要計算機容易算,但思路基本是同源的。擅長數學或者搞過數學競賽的人搞起acm也是如魚得水(如rng_58,quailty)。

ACM的大方向

  • 亂搞(雜湊,小模擬,預處理,貪心,列舉,搜尋),通常較易,也有難題
  • dp,難易度變化大,腦洞
  • 圖論,較難,常有銀牌金牌題
  • 資料結構,難易度變化大,模板好用
  • 計算幾何,常有幾何壓軸題,程式碼量長
  • 字串,常常有對應資料結構,有色牌
  • 數論,組合,概率論各類數學,常常融入題目中,單獨出現則不是很難就是很簡單。
  • 大模擬,通常為銀牌之後,強隊才會練

以上為基本的大方向,但可怕的是常常出現演算法的組合,dp,資料機構,數學常常與其他知識組合出現。許多問題可以轉化為圖論解決。另外很多偏門,奇怪的知識都能在ACM得到運用。

dp,亂搞,模擬之外的基本都是能夠建立模板的,挑選常用的演算法封裝為好用的模板可以大大增快寫題的速度。

個人認為初期的時候可以多訓練一些簡單的題把握好基本的語言。之後可以找本書入門,再由圖論或者dp入手開始掌握一些演算法題,因為這兩個方向題量充足,ACM中出現頻率也高,各個檔次的題目都有。然後其他方向的簡單演算法也可掌握,待到基本沒有特別短板可以找自己喜歡的方向深入挖掘。

讀物推薦

  • 《程式碼大全2》可以瞭解下其中對於程式碼風格的闡述,寫好看程式碼是件好書。
  • 《挑戰程式設計競賽》入門書籍,程式碼優美,翻譯清晰,好書!可作模板,有語言基礎去讀。
  • 《演算法導論》有志於科研或者瞭解演算法背後機理的推薦,不推薦用作入門或者帶去賽場,題好。
  • 劉汝佳系列,入門經典適合無語言基礎的,有基礎可略過部分,訓練指南可用作提高。
  • 《具體數學》各類計算機數學,題好,可用於數學進階。
  • 餘勇系列,哈工大系列,均為套書,強大的模板套裝,也可用作學習,進階用。
  • 各類數學去學習教材即可,《運籌學》《概率論》《計算幾何》《初等數論》
  • 各路大牛的程式碼/部落格,挑風格好,程式碼清晰的,條理清晰的。如ACdreamer 叉姐(ftisach) TankEngineer Petr!