引論:這是第二次在演算法課上的上機實踐了,雖然逐漸有了思考演算法的感覺,但這一次上機實踐還是並不輕鬆。關鍵在於在實驗課前對第三章的知識掌握得還不足夠,經常會因為明明知道理論上如何解題而苦於無法將其實現。不過,通過本次上機實踐,我的收穫是非常豐富的,下面用實踐課題目中的第一題《數字三角形》開始分享我的經驗。
給定乙個由 n行數字組成的數字三角形如下圖所示。試設計乙個演算法,計算出從三角形的頂至底的一條路徑(每一步可沿左斜線向下或右斜線向下),使該路徑經過的數字總和最大。
輸入有n+1行:
第 1 行是數字三角形的行數 n,1<=n<=100。
接下來 n行是數字三角形各行中的數字。所有數字在0-99 之間。
輸出最大路徑的值。
在這裡給出一組輸入。例如:
5
7 3 8
8 1 0
2 7 4 4
4 5 2 6 5
在這裡給出相應的輸出。例如:30
初看這一道題的時候,差點陷入到了迷惑之中,不過簡單分析一下題目後發現是那樣的熟悉——題目要求我們從數字三角形的最頂端數字開始,選取一條能夠使經過的數字總和最大的路徑。而這不就和老師在第三章開頭課說的例子一樣嗎?從a地到d地選取一條經過b、c兩地的最短路徑。a到d的最短路徑取決於b到d,而b到d取決於c到d。我們將這種思想反推至這道題目,要求出數字三角形的最短路徑,從頂部數字開始到底部數字,這要先取決於頂部數字到第二行的最大和,再取決於第二行數字到第三行的最大和,以此類推至數字三角形的最後一行。好的,有了這種動態規劃的思想我們離解決問題還有一半距離了!
那麼我們開始分析,因為每一行的最大和都取決於上一行的數字最大和,那麼,我們自底而上分析,重填輸入進來的二維陣列。重寫時,數字三角形的最後一行是不變的,因為最後一行的數字們沒有下面一行的數字影響,而從倒數第二行開始,這些數字重寫後變為,它自身與和它相鄰的最後一行兩個數字之和的最大值。舉個例子,即a[i][j]的大小是max。那麼我們自下而上重寫陣列,最後得到新的最頂端的數字,即是最大值路徑。
首先列出我解題的**
1 #include 2 #include 3因為改寫後的陣列,數字三角形的最後一行是不變的,所以我們的第一層迴圈從倒數第二行開始,因此定義i = n - 2,並讓i不斷變小;在第二層迴圈中,我們分析的是當前行的每個數字,每一行的數字數目為該行行號,而i為每一行的下標,所以定義j = i + 1。而我們填入陣列的是該行數字和與它相鄰的下一行數字組成之和的最大值。最終迴圈結束後,我們直接輸出陣列的第乙個數字,即得到最大路徑和。using
namespace
std;45
intmain()618
}1920//
用動態規劃的思想,改寫array二維陣列
21for (int i = n - 2; i >= 0; i--) //
因為數字三角形的最後一行的動態規劃最大值是自己,所以從倒數第二行開始求自下而上時的動態規劃最大值
2227
}28 cout<0][0]; //
因為是自下而上求最大值,所以二維陣列第乙個元素即是數字三角形的最大值
29return0;
30 }
對於時間複雜度:本演算法為main函式中的重疊的兩個for迴圈,而第一層迴圈是從n-2開始至0,第二層迴圈為從0開始至n-1,因此不難得出,本演算法的時間複雜度為o(n^2)。
對於空間複雜度:因為本題是直接改寫輸入進來二維陣列,所以沒有額外申請陣列和記憶體空間,所以空間複雜度為o(1)。
通過本次上機實踐,我更好地鞏固了第三章的知識,動態規劃思想理解起來不難,但需要多次的動手實踐來讓自己真正掌握它。通過自己動手程式設計解決這一道題讓我加深了上節課所學知識的印象。在想出上述解題演算法之前,我在草稿本上列出了很多種填表的方式,但難以實現出來,即使解決了這一道題,我目前對填表法的掌握還並不熟練。不過,通過做這一道實驗題,我真正明白了動態規劃思想的厲害之處。因為實驗題目集中的第二題是書上的原題,所以相對於第二題,我在第一題花費的時間較多。因此,在解決動態規劃思想的題目中,我們不能糾結於如何寫出完完整整的遞推式,而要多結合題目實際。
同時,解決這道題目也不僅僅是我乙個人想出來的,這道題目的核心思想是我的搭檔為我講解的,因此光靠自己乙個人我是無法解決這道題目的。這又再次體現出結對程式設計的重要性,兩個人的頭腦風暴得出來的結果是實驗課中最好的成果。
通過本次實驗,我希望自己能夠再接再厲,不斷鑽研演算法知識,爭取解決更多的問題!
演算法第三章上機實踐報告
一 實踐題目 7 2 最大子段和 給定n個整數 可能為負數 組成的序列a 1 a 2 a 3 a n 求該序列如a i a i 1 a j 的子段和的最大值。當所給的整數均為負數時,定義子段和為0。要求演算法的時間複雜度為o n 輸入格式 輸入有兩行 第一行是n值 1 n 10000 第二行是n個整...
演算法第三章上機實踐報告
7 1 數字三角形 30 分 給定乙個由 n行數字組成的數字三角形如下圖所示。試設計乙個演算法,計算出從三角形 的頂至底的一條路徑 每一步可沿左斜線向下或右斜線向下 使該路徑經過的數字總和最大。1.路徑經過的數字總和最大 2.每一步可沿左斜線向下或右斜線向下 1 由題目可知從上到下,只能往左或者往右...
演算法第三章上機實踐報告
1.實踐題目 給定n個整數 可能為負數 組成的序列a 1 a 2 a 3 a n 求該序列如a i a i 1 a j 的子段和的最大值。當所給的整數均為負數時,定義子段和為0。要求演算法的時間複雜度為o n 2.問題描述 題目要求時間複雜度為o n 所以只能用乙個for迴圈解決問題,要用到動態規劃...