不知不覺暑假就要這樣結束了,這個假期主要在弄acm了,但是由於家裡原因並沒有來學校參加集訓,而是在家裡跟著學知識點刷題做練習賽。
程式設計作為計算機的基礎以及入門知識,其重要性自然不用說,而且大一剛開始就是學演算法,當時感覺程式設計挺感興趣的,然後參加那個新生程式設計賽。剛開始接觸到acm也是在這次新生程式設計比賽上吧,當時聽到學長對
acm的介紹後,感覺挺感興趣的,再加上當時感覺程式設計也是挺有意思的,然後大一寒假就加入了體味
acm那個群,學習群裡的課件,刷題練習,當時真的學到了不少演算法知識,雖然對於現在來說只是很小的一部分,但是當時真的感覺挺有成就感的。同時通過刷題也對演算法有了更深入的理解跟掌握,而且還有很多程式設計的小細節可以注意到,對程式設計很有提高。同時還有定時的比賽,可以通過比賽加強對時間的掌握,其次還可以體味到競賽的樂趣。
就這樣大一下學期自然選了acm這門選修課,當時這門選修課需要耗費的時間跟精力不亞於高數、大物這種難度有點大的必修的,但是挺充實的,而且還學到了很多程式設計知識,同時也結交了很多志同道合的朋友。這門課不只是上課聽課,課下自然還伴隨著練習題跟比賽以加強對演算法的理解跟掌握。教
acm的是費老師,同時是我們學校
acm的教練,他真的是乙個很盡職盡責的老師,不只教學認真,而且還總是開導我們,讓我們大學專心做好該幹的是,不要在大學浪費美好的時光。
不知不覺大一下學期就這樣過去了,然後伴隨而來的就是暑假集訓。暑假集訓從放假一周後就開始了,剛開始是熱身訓練,基本都是動態規劃問題,大部分都是以前的原題。然後再過一周後才算正是開始吧,剛開始為期10天的的訓練一主要是訓練
dfs深搜跟
bfs廣搜以及最短路跟最小生成樹的問題。
dfs深搜從初始狀態,利用規則生成搜尋樹下一層任乙個結點,檢查是否出現目標狀態,若未出現,以此狀態利用規則生成再下一層任乙個結點,再檢查,重複過程一直到葉節點(即不能再生成新狀態節點),當它仍不是目標狀態時,回溯到上一層結果,取另一可能擴充套件搜尋的分支。採用相同辦法一直進行下去,直到找到目標狀態為止。深搜主要靠遞迴呼叫函式來完成操作,用陣列或變數進行標記操作來控制迴圈的結束。
bfs廣搜是從初始狀態
s開始,利用規則,生成所有可能的狀態。構成的下一層節點,檢查是否出現目標狀態
g,若未出現,就對該層所有狀態節點,分別順序利用規則。其主要用佇列
queue
的相關操作來完成,一般會與結構體相結合來儲存相關的條件以及對應的搜尋次數,
bfs廣搜主要是用來解決最小運算元問題。
最短路徑問題為給定帶權有向圖g=
(v, e)
和源點v∈v
,求從v到g
中其餘各頂點的最短路徑。主要有
bellman-ford
演算法、spfa
演算法、dijkstra
演算法、floyd-washall
演算法,雖然不同演算法的思路有所不同,但是核心演算法還是相同的,同時不同演算法有他們分別的優缺點。
dijkstra演算法的效率高,但是也有侷限性,就是對於含負權的圖無能為力。
bellman-ford演算法對於所有最短路長存在的圖都適用,但是效率常常不盡人意。
spfa演算法可以說是綜合了上述兩者的優點。它的效率同樣很不錯,而且對於最短路長存在的圖都適用,無論是否存在負權。它的程式設計複雜度也很低,是價效比極高的演算法。
最小生成樹問題為由g的
n-1條邊構成的無環的子圖,這些邊的集合成為生成樹。所有生成樹中權值最小的乙個邊集
t為最小生成樹,確定樹
t的問題成為最小生成樹問題。主要演算法有
prim
演算法、kruskal
演算法。kruskal演算法:將邊按權值從小到大排序後逐個判斷,如果當前的邊加入以後不會產生環,那麼就把當前邊作為生成樹的一條邊。最終得到的結果就是最小生成樹。
prim演算法:設
g=(v,e)
是連通帶權圖,
v=。構造
g的最小生成樹的
prim
演算法的基本思想是:首先置
s=,然後,只要s是
v的真子集,就作如下的貪心選擇:選取滿足條件iî
s,jî
v-s,且
c[i][j]
最小的邊,將頂點
j新增到
s中。這個過程一直進行到
s=v時為止。在這個過程中選取到的所有邊恰好構成
g的一棵最小生成樹。
最短路徑跟最小生成樹的演算法雖然很多,各個演算法也各有千秋,但是感覺最短路徑跟最小生成樹的難度並不是很大,只要理解好各種演算法,掌握各種演算法的優缺點,在看到題目的時候知道套用哪個演算法,只要對應正確問題差不多就很好解決了。
接下來就是訓練二,訓練二主要練習了二分、單調佇列、單調棧問題。其中二分是以前學過的,並且當時也做了不少練習題,做起來還是比較順手的。
二分是在乙個單調有序的集合中查詢元素,每次將集合分為左右兩部分,判斷解在哪個部分中並調整集合上下界,重複直到找到目標元素,將時間複雜度從o(n)縮短為
o (logn)
。由於其二分演算法可以降低時間的複雜度,所以很多其他題目中也會用到二分演算法。
同時還有比二分更進一步的三分演算法,當需要求某凸性或凹形函式的極值,通過函式本身表示式並不容易求解時,就可以用三分法不斷逼近求解。三分法跟二分法演算法類似,其基本演算法去下:
mid = (left + right) / 2
midmid = (mid + right) / 2;
如果mid靠近極值點,則
right = midmid
;否則(即
midmid
靠近極值點),則
left = mid;
單調佇列是佇列中元素之間的關係具有單調性,而且,隊首和隊尾都可以進行出隊操作,只有隊尾可以進行入隊操作。
單調佇列的常用操作如下:
(1)插入:若新元素從隊尾插入後會破壞單調性,則刪除隊尾元素,直到插入後不再破壞單調性為止,再將其插入單調佇列。
(2)獲取最優(最大、最小)值:訪問首尾元素。
單調棧,跟單調佇列差不多,但是只用到它的一端。單調棧裡的元素具有單調性。元素加入棧前,會在棧頂端把破壞棧單調性的元素都刪除。所有元素只會進棧一次,並且出棧後再也不會進棧了。使用單調棧可以找到元素向左遍歷的第乙個比他小的元素,也可以找到向左遍歷第乙個比他大的元素。
單調佇列跟單調棧的主要區別為:單調佇列隊首跟隊尾都可以進行出隊操作,雖然入隊操作只能在隊尾進行;但是單調棧的入隊跟出隊操作只能在棧頂進行。
訓練三照樣還是資料結構問題,主要為樹狀陣列問題跟線段樹問題。
數狀陣列是乙個查詢和修改複雜度都為log(n)的
資料結構
。主要用於查詢任意兩位之間的所有元素之和,但是每次只能修改乙個元素的值;經過簡單修改可以在log(n)的複雜度下進行範圍修改,但是這時只能查詢其中乙個
元素的值(如果加入多個輔助陣列則可以實現區間修改與區間查詢)。
樹狀陣列非常的巧妙,能大大提高效率,難點就是不好往這個方向想。主要解決單點更新和區間查詢或者區間更新和單點查詢還有就是求逆序列對。
線段樹,類似區間樹,是乙個完全二叉樹,它在各個節點儲存一條線段(陣列中的一段子陣列),主要用於高效解決連續區間的動態查詢問題,由於二叉結構的特性,它基本能保持每個操作的複雜度為o(lgn)!父親的區間是
[a,b],(c=(a+b)/2)
左兒子的區間是
[a,c]
,右兒子的區間是
[c+1,b]。
線段樹最大缺點為需要的空間太大,需要的空間為陣列大小的四倍。
能用樹狀陣列解決的問題,都可以用線段樹來解決,反之則不一定。另外就是樹狀陣列有很多都是模板題,到時候可以直接套用模板來做題。
同時樹狀陣列跟線段樹問題資料量一般都比較大,尤其再就是求和問題,資料會賊大。所以有些資料要用long long型變數,有的時候甚至要用到
64位整型才可以。
通過這次暑假的集訓收穫很多,學到了很多演算法、很多知識,對程式設計更加熟練了,程式設計錯誤早已不是問題,而且還會了挺多優化程式的演算法或小方法。同時對細節的掌握也更好了,同時還能鍛鍊自己的耐力,比如比賽一次就是連著三四個小時,而且還能鍛鍊團隊協作能力,加強同學間的友誼。
acm是一件值得做的事,接觸
acm有半年多了,雖然任務很重,時間很緊,實話有點忙,但是真的很充實,而且能學到很多東西,對程式設計能力的提公升很有幫助。同時
acm也很有深度,很有挑戰,感覺挺有意思的,也挺感興趣的,希望自己繼續堅持下去,同時祝跟自已一起的
acmer
們也能夠繼續走下去,早日達到自己目標的高度!
暑假訓練總結 SSL暑假訓練總結
第一周過的還算好吧,覺得飯堂伙食也挺好的,同學也挺好。學習的東西感覺比小學難好多,有種覺得以前學的東西太簡單了的感覺,但多虧了小學的時候基礎打得還算紮實,學得還行,但總是感覺自己就是個菜雞,就是乙個蒟蒻,哎,室友真的太強了。第一周總結 第二週自我感覺挺不錯的,總算追上了部分室友,成績也開始 這一切都...
暑假訓練總結
社會實踐調查報告 題目 關於暑假acm訓練的實踐與總結 專業班級 數學與應用數學專業1班 姓名 李雙智 學號 20164249 2017年8 月25日 摘要 31.樹狀陣列和圖論 42.二分三分以及單調佇列 53.樹狀陣列與單調佇列 54.總結6 摘要 本文主要總結了這個暑假acm實踐的主要內容,以...
暑假訓練總結
這一暑假的訓練結束了,感覺自己仍然是一條鹹魚.一暑假的訓練不僅回顧了之前的知識,還學習了新的知識。首先是複習了搜尋的知識,個人感覺搜尋的題目一般 都比較長 也許是自己寫的太囉嗦,廢 太多.而有時候往往在一些不經意的地方而出錯,所以搜尋的題目一般要仔細的把握,不能在一些地方潦草而過,往往會在下面就卡住...