ACM課程學習總結

ACM課程學習總結報告html

       經過一個學期的ACM課程的學習,我學習了到了許多算法方面的知識,感覺到了算法知識的精彩與博大,以及算法在解決問題時的巨大做用。此篇ACM課程學習總結報告將從如下方面展開:算法

       學習ACM算法知識以前的具有的知識基礎數組

       學習過程及知識梳理數據結構

       心得體會及收穫函數

一,學習ACM算法知識以前具有的知識基礎學習

       在開始這一學期的課程以前,大一上學期及寒假期間我學習了C++標準庫中的STL,瞭解了一些通用操做,各類類型的容器的特性,以及一些算法。關於算法,只學習了一些簡單的遍歷,遞歸。並未深刻學習。優化

二,學習過程及知識梳理htm

       1. 遞歸對象

       遞歸併非在ACM課上學習的,是在C++的課上獲得了講解。寫在這裏是由於我覺的遞歸是很重要的一種方法或者說思想。在上學期我本身瞭解了一下遞歸,自覺得已經掌握了遞歸。在這一學期開始深刻了解以後發現有一些有趣的地方。排序

       首先,遞歸的具體含義是:遞歸_計算機科學(來自維基百科)。

這篇文章說的很清楚:

遞歸是經過重複將問題分解爲同類的子問題而解決問題的方法

具體在C/C++中,是指在函數中調用函數自己。

在我看來,遞歸與循環有類似之處,都是下一輪與上一輪進行一樣的操做,因此有時候遞歸能夠與循環相互轉化。但循環與遞歸也有不一樣之處,循環是單向的,遞歸有一個返回過程,並且,遞歸是從結果出發的,方向不一樣;另外,遞歸能夠用於在計算開始不肯定層數的狀況,而循環則不能夠;

我以爲這句話說的很好:

        遞歸的強大之處在於它容許用戶用有限的語句描述無限的對象。所以,在計算機科學中,遞歸能夠被用來描述無限步的運算,儘管描述運算的程序是有限的。

    ——尼克勞斯·維爾特

但我認爲在C/C++中能夠用循環(遞推)的地方應該避免用遞歸,由於C/C++中的遞歸每產生新的一層運算就要產生新的堆棧,這無疑下降了效率。

       這也是我在剛開始學習的時候以爲遞歸無用的緣由,但在後面的學習中,我發現有不少算法用遞歸來理解更加容易方便,更接近數學。好比在搜索的相關算法的學習中,遞歸實現就重要。

       2.貪心算法與動態規劃

       貪心與動態規劃有許多類似之處

       費老師在一開始講貪心時就說,貪心是最容易的算法了,貪心的題目也是可遇不可求的。。。。貪心理解是一種在每一步選擇中都採起在當前狀態下最好或最優(即最有利)的選擇,從而但願致使結果是最好或最優的算法。適用於子問題的最優解組成了最終問題的最優解的狀況,也就是說具備最優子結構的問題。

       貪心算法的經典模型:

              (1)揹包問題(最優裝載): 

       給定n個物品和一個容量爲C的揹包,物品i的重量是Wi,其價值爲Vi,揹包問題是如何選擇入揹包的物品,使得裝入揹包的物品的總價值最大。

在揹包問題中能夠將物品的一部分裝入揹包,但不能重複裝入。

揹包問題的貪心原則就是儘量選擇單位重量價值最大的物品。

解決揹包問題時首先按照物品的」性價比「(Vi/Wi)由大到小排序,而後順序選擇物品直至揹包裝滿。

              (2)區間相關問題

       區間問題是可抽象爲多個線段之間的關係的一類問題,不一樣的類型的區間相關問題有着不一樣的貪心原則,具體在程序上就表如今線段區間的不一樣排序方式以及可行區間的篩選方式。

就我刷過的題目來看,區間相關問題模板化很強,基本只要將問題抽象成區間(線段)之間

的關係,運用不一樣的排序原則及不一樣的貪心原則選擇可行區間便可。

       3.搜索

       搜索是很重要的一種算法,應用範圍很廣,並且在以後圖論的學習中是很關鍵的知識點,在劉汝佳的紫書中是將搜索放在了圖論專題之下,不少資料也是將搜索做爲圖論的一個子專題。

       老實說,個人搜索掌握的很差。因此正好趁寫這個報告的機會,將搜索專題總結複習一下。

       搜索分爲DFS(深度優先搜索),BFS(廣度優先搜索)(BFS與DFS對圖進行搜索),此學期ACM課程還介紹了兩種方法二分法與三分法;

              (1)BFS

       搜索完一層以後才進行下一層的搜索工做,隊列的先進先出性質可很好的實現BFS。

       首先將隊首元素(未到達節點)取出;拓展此節點並經拓展後產生的新節點放入隊列(沒法產生新節點則直接刪除隊首元素);刪除隊首元素;循環進行以上步驟直至隊列爲空

       BFS找到的問題的解必定是最優解。

       下面是廣搜的僞代碼,BFS是一種層次遍歷,無需用到遞歸便可方便的實現:

 

While 隊列不爲空 do

    Tmp <- 隊首元素

    從Tmp循環拓展下一個狀態Next

    If 狀態Next合法 then

           生成新狀態Next

           Next.Step = Tmp.Step + 1

           將Next放入隊列

           End

    刪除隊首元素

    End

 

廣度優先遍歷演示地址:

http://sjjg.js.zwu.edu.cn/SFXX/sf1/gdyxbl.html

 

              (2)DFS

       DFS是按照從初始狀態生成下一層的任一節點,判斷目標狀態是否出現;若未出現,返回上一層繼續上一步驟,直至不能產生新的狀態的節點;若仍不能找到目標狀態,則返回上一層,至上一層的下一個節點繼續擴展;重複以上步驟,直至找到目標狀態。

       相較於BFS,DFS能夠更快的找到目標狀態,但有時找到的解不必定是最優解

       很明顯DFS運用了遞歸的思想,能夠運用遞歸來實現

       DFS的遞歸實現與非遞歸實現都運用了棧的先進先出的性質,相似於BFS利用隊列來實現,DFS利用棧來實現的思路是:

1 每次取出棧頂元素,對其進行拓展。

2 若棧頂元素沒法繼續拓展,則將其從棧中彈出。繼續1過程。

3 不斷重複直到得到目標狀態(取得可行解)或棧爲空(無解)。

       具體的實現的僞代碼爲:

       非遞歸實現:

    While 棧不爲空 do

        Tmp <- 棧頂元素

       從Tmp拓展下一個未拓展的狀態Next

           If 沒有未拓展狀態(到達葉節點) Then

              刪除棧頂元素

           Else If 狀態Next合法 Then

              將Next壓入棧

      End

       遞歸實現:

    Function Dfs (Int Step, 當前狀態)

      Begin

        可加結束條件

        從當前狀態循環拓展下一個狀態Next

           If 狀態Next合法 Then

               Dfs (Step + 1, Next ))

      End

 

              (3)二分搜索與三分搜索

       二分搜索與三分搜索的原理都很簡單,即不斷縮小搜索區間,直至找到解

       二分搜索要求搜索對象單調且無重複;

       三分搜索是在二分搜索的基礎上對右區間或左區間再進行一次二分,適用於凸性函數,便是該函數必須有一個最大值(或最小值),在最大值(最小值)的左側序列,必須知足不嚴格單調遞增(遞減),右側序列必須知足不嚴格單調遞減(遞增)。

       爲了提升效率,二分搜索與三分搜索通常使循環實現,不使用遞歸

       4.動態規劃

       就我而言,這學期最難的一塊內容就是動態規劃了,只要問題有具備最優子結構就可以使用動態規劃來解決。使用動態規劃解決問題的過程當中,最關鍵的無疑是找到子問題的分解方式與狀態轉移方程了。有的簡單問題能夠遞推直接解決這兩個問題,而有關一些複雜的問題,能夠找到許多經典模型:

              (1)揹包類問題

       揹包類問題的範圍很大,從最基礎的01揹包與徹底揹包,衍生出許許多多的揹包類問題。《揹包九講》寫的很好,給了我很大啓發。具體的思路與代碼實現就不在此報告裏贅述了。揹包問題的變化很豐富,要注意分辨清楚

              ( 2 ) 最大遞增子序列與最長公共子序列

       最大遞增子序列問題的狀態轉移方程爲:F(k) = Max { F(i); 1<i < k 且 a[i] < a[k] } + 1

最長公共子序列的遞推公式爲

 

5.圖論

圖論與dp是這學期最大的兩個專題了。在這一專題裏,首先了解了圖數據結構的一些基礎知識以及圖的存儲方式,我感到最有趣的就是鄰接表的數組表示形式了,開銷低且高效,感受甚是神奇,下面貼出鄰接表的數組表示形式:

 

struct edge

{

    int x, y, nxt; typec c;

} bf[E];

void addedge(int x, int y, typec c)

{

    bf[ne].x = x; bf[ne].y = y; bf[ne].c = c;

    bf[ne].nxt = head[x]; head[x] = ne++;

}

 

       基礎知識學習瞭解以後,又學習了並查集,經過對並查集實現的按部就班的一次次優化,越發感受到思考的力量,我以爲這是這學期ACM課程中最有趣的一部分了。

學習完了並查集,又學習了最小生成樹的幾種經典算法:prim算法,kruskal算法

       及解決最短路問題的三種算法:Dijkstra算法,Bellman-Ford算法,spfa算法(Bellman-Ford算法的隊列實現)

       至此,這學期的ACM課程就結束了。

三,心得體會及收穫

       收穫固然是以上提到的算法知識了,體會到了算法是頗有趣的,更重要的是初步學習到了如何解決問題(不敢說徹底學習到了。。。)。這東西比較虛,但在作應用軟件時,明顯體會到了學過ACM或者說算法的優點:不只僅給我增長了自信,思考問題也更加深刻,同時代碼實現的能力也好一些。

       除了以上這些,經過ACM課程我還認識了許多比本身強,比本身努力的人;也經過各類渠道瞭解到了山農以外的牛人是多麼牛。我意識到本身以前看到的那片天空是多麼眇小,爲那些不能稱之爲成績的「成績」而沾沾自喜是多麼幼稚;這給了我努力的動力與靜下心來的理由。這或許是對我改變最大的一點吧。

                                                                                                         2016年6月30日

                                                                                                                劉佔山

相關文章
相關標籤/搜索