Code Craft 2016初賽的一點體會

2021-07-13 06:56:46 字數 3253 閱讀 7559

華為codecraft軟體精英挑戰賽初賽於4月11日結束,我們的隊伍有幸進入南京蘇州賽區32強,順利晉級將於5月中旬舉行的複賽。

初賽持續了整整乙個月。這乙個月下來,還是很累的。比賽的競爭非常激烈(個人感覺,南京蘇州賽區是全國八大賽區競爭最激烈的),基本上就一直在不停地想新的演算法以及優化**。

賽題描述起來還是很簡單:給你乙個圖,求一條從起點到終點的最短路徑,但是要經過一些指定的中間節點,並且不能重複訪問任何乙個節點。然而想要解決它可就沒那麼容易了——這是乙個np-hard問題,不可能有多項式時間演算法。話說要是有多項式時間演算法的話,也不會被拿來當賽題了。

在比賽的前期,官方**上只放出了10個初級和中級測試用例,圖的規模不是很大,必經點數量也不算很多。我們最初的演算法就是暴力列舉+剪枝,基於dijkstra演算法,當然這個方法是無法解決稍大一點的用例的,因為列舉的複雜度是指數級的,剪枝也有不同的方法,有人剪得好效果就比較好(怎麼說,感覺還是有人品的成分在裡面)。然後我們開始嘗試啟發式演算法,最先寫的是a star演算法,a star演算法的難點在於對於不同的問題要設計合理的啟發式函式,寫完後經過一些優化,提交後,效果很好。在比賽的前中期,因為a star演算法的使用,我們最好的成績曾進過賽區前三名。

到了比賽的後期,高階測試用例放出來了。a star演算法沒能解出部分高階用例,所以,我們又開始設計新的啟發式演算法。我們實現了遺傳演算法,並且也幾經優化,嘗試了很多技巧。遺傳演算法的引數以及各種遺傳運算元都有可能極大地影響程式的效能。後來,我們使用了混合演算法——將遺傳演算法和前面的列舉、a star結合起來用,對不同規模的測試用例跑不同的演算法,終於解出所有用例,分數也上到了90+。然而排行榜上競爭異常激烈,雖然一直保持在32強,也解出了所有用例,但是我們的名次也基本上是一直在下降。因為不斷有隊伍解出更好的解。這個時候,基本上我們能想到的方法也都嘗試過了,**也很難再有顯著的優化。如果沒有更好的演算法,進複賽恐怕還是不能保障。

我開始留意比賽論壇上的各種資訊,發現很多隊都開始採用開源庫,通過整數規劃來求解賽題。因為比賽規則中說明了初賽可以使用開源庫,但是複賽不能使用。所以我們從一開始就沒打算走這種路子,心裡也鄙視這種做法(因為畢竟你只是呼叫別人的api,而不是自己一行一行寫出來的)。用開源庫也不是那麼容易的,首先要能夠把問題抽象成合理的數學模型,然後才能使用開源庫,而且要閱讀開源庫的使用文件,熟悉了它的api才行。於是,清明節的三天假期,我就在實驗室裡研究開源庫,基本了解了用法,寫出了一些測試程式,後來在小夥伴的協作下完整地實現了整數規劃模組。實驗室裡也有個隊伍,他們清明節之前也解出了所有15個用例,上了90分,於是他們認為應該可以穩進複賽了,清明節三天就出去玩了,等他們回來後檢視排行榜,發現名次掉了十幾名,一下子就被擠出了32強……

「嘴上說不要,身體還是蠻誠實的」。雖然我們一開始鄙視用開源庫,最後還是採用了。因為當大家都在使用開源庫而且效果比你完全靠自己寫**好得多時,你就得考慮是不是要轉型了。也許你稍微一遲疑,就被遠遠地甩在後面,並且再難趕上。後來在論壇裡,許多參賽選手抱怨比賽不公平,抱怨真正靠自己能力手寫演算法的人被「沒有能力的」靠開源庫的人超越。我也想了這個問題,最後得出的結論是,開源庫並不是萬能的,會使用開源庫的人,自己設計的演算法大概也不會差到**去,而且使用開源庫是初賽允許的,既然允許,那選手就有自由決定是否採用。你既然覺得不公平覺得那些使用了開源庫的人都是「渣渣」,那麼最好的辦法是,你也使用開源庫,然後打敗那些同樣使用了開源庫的人

正如戰場上允許使用劍和自動步槍,雖然少數用劍的人能夠靠著自己精妙絕倫的劍法叱吒戰場,但不幸的是大部分使用劍的人都被使用自動步槍的人秒殺,但是你不能因為自己劍法好就說那些使用槍的人都是渣渣。畢竟,能用劍擋住子彈的人永遠是極少數。

最後我們的演算法是整數規劃+遺傳演算法。即使用開源庫,也不是就所向披靡了。在同乙個問題上,採用不同的開源庫,以及建模方法的不同,都會導致效能也不盡相同。比如我們使用的開源庫就無法解決最後兩個測試用例,所以還是採用了混合演算法。最後的分數定格在96,也順利地闖進複賽。

從3月19日第一次到4月11日最後一次,我們累計提交了110次**。以下是部分提交後的截圖,分別對應「第一次提交」 「第一次嘗試a star演算法」 「第一次用列舉+astar+遺傳解出所有15個用例」以及「最終的版本——整數規劃+遺傳演算法」:

至於感想,多少還是有些的。團隊合作不必多說,就算乙個團隊裡沒有大神,不錯的合作大抵也能起到「三個臭皮匠頂個諸葛亮」的效果;然後就是要不斷嘗試新的idea,不能因為一點小小的進步就自滿得意,因為很多時候競爭對手的實力會超出你的想象;另外就是要廣泛獲取有價值的資訊,關注比賽動態,看看別人都在嘗試哪些路子,也許可以幫助自己獲取新的idea,這樣可以避免固步自封。最後就是足夠的時間與付出了,初賽的乙個月,雖然我們手頭也都有自己的事,但是基本上每天都在提交**,累計寫的**估計有3000+行。後來華為組織的複賽隊伍的見面活動,還了解到有隊伍**寫了5000+行的。當然不是說**量越大越好(聽說也有隊伍用500行左右就上97分),但是**量至少從乙個方面反映了乙個隊伍在這項活動中付出的努力。粗略地了解過,基本上初賽進了top64的,大概累計**量都不會少於1000行。

其實我們一開始並沒有什麼目標,就是覺得這個比賽看起來組織得不錯(雖然後來競賽規則遭到了很多選手的吐槽),獎勵也比較可觀,就抱著玩一玩的心態報了名。參加了比賽之後只想著能進複賽就好了,誰知競爭程度遠比自己想象的還要激烈,每次只要一有「差不多能進複賽了吧」「這樣還不進複賽!」的想法,往往過不了幾天就要被打臉。那種眼睜睜地看著自己隊伍名次一直往下掉,而自己卻無能為力的感覺,真心不好受。但是又不忍放棄。比賽論壇上也不斷地有選手喊「心累」,但大家依舊是在不停的寫著**,討論著什麼演算法好,不論是大神還是菜鳥。努力不懈的程式設計師們永遠都是那麼可愛。

據說初賽的獎勵除了紀念品和證書,還有「實習直通車」,好像可以不用面試就能去華為參加實習;以及校招免技術面,只有乙個hr面,過了就能拿special offer。不過這些倒不是我最關心的,華為能否兌現承諾也無所謂了。好好珍惜最後兩年多的學生生涯是我目前的想法,雖然聽起來有點*****。

不過作為自己給自己的獎勵,我買了人生第一副機械鍵盤——cherry mx board 2.0。

上上週去華為南研所參加複賽36支隊伍的見面活動,發現原來在群裡給人感覺牛x得一塌糊塗的大神們乙個個都是那麼的靦腆羞澀,反倒是一些隊裡的妹子表現得比較大方。一頓免費的午餐之後,順便和同去的同學們逛了南研所,風景挺好的,而且坐落於郊區比較安靜,這張黑天鵝**,就是在南研所拍攝的。只是南研所的氛圍沒有我想象得那麼活躍,大概研究所都是這個樣?

關於複賽,依舊沒有什麼特別的想法。只要到時候不要被大神們虐得太慘,就心滿意足了。

小華 2023年5月2日 於 東南大學

華為CodeCraft2016比賽的個人的演算法優化

參加了2016華為codecraft比賽受到刺激很大,感覺被那些牛人秒成渣渣.要更努力啊 我已經 光榮犧牲 了,所以也就沒什麼心理負擔了.題目如下 給定乙個帶權重的有向圖g v,e v為頂點集,e為有向邊集,每一條有向邊均有乙個權重。對於給定的頂點s t,以及v的子集v 尋找從s到t的不成環有向路徑...

2016計蒜之道初賽

官方題解 另外搜尋題解的時候看到乙個很有意思的部落格.大一進省賽的妹子otz 畫出以頂點 o 為公共頂點的 夾角為 的兩條線段l1和l2,其中l1作為圓 c1的直徑,l2作為圓 c2的直徑。兩個圓需要畫在同乙個圓形的塑料板上。請算出這個塑料板最小的面積是多少。字串處理 很坑的是oj 測試 只是測試能...

NOIP2016初賽總結

第一篇部落格。明明老早就註冊了,但一直都懶得寫 話說這裡提供的的為什麼是qq表情,還想加個滑稽來著 咳咳,這都高二了。再不留點東西感覺說不過去。感覺現在寫這個有點早,畢竟還不知道成績。沒有核對多少答案。薛丁格的分數 理論告訴我們在真正發布成績之前,我的分數既是零分也是滿分。所以我現在不敢立flag。...