7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
在上面的數字三角形中尋找一條從頂部到底邊的路徑,使得路徑_上所經過的數字之和最大。路徑上的每一步都只能往左下或右下走。只需要求出這個最大和即可,不必給出具體路徑。
解決思路是採用遞迴演算法,每個節點只加上,左下和右下兩個資料,即
int x = maxsum(i+1, j); // 左下
int y = maxsum(i+1, j+1); // 右下
這樣每一層就會形成兩條分支,直到遞迴到最後一層,求出最大的和,然後退出。
對程式進入maxsum進行計數可以得到一共32次,即2^5
2
52^5
25:是怎麼計算得到的
應該反推這個問題,當第四層到第五層時,一共需要有4∗2
4*24∗
2次,同理第三層到第四層就需要4∗2
∗2
4*2*2
4∗2∗
2,以此類推到第一層4∗2
∗2∗2
4*2*2*2
4∗2∗2∗
2,這就是解決這個問題需要進行的計算次數。
#include #include #include using namespace std;
#define max 101
int d[max][max];
int n;
int max_count = 1;
int maxsum(int i, int j)
int x = maxsum(i+1, j);
int y = maxsum(i+1, j+1);
return max(x, y) + d[i][j];
}int main()
}cout << maxsum(1, 1) << endl;
cout << "max_count:" << max_count << endl;
cout << max_count << endl;
return 0;}/*
輸入:5
73 8
8 1 0
2 7 4 4
4 5 2 6 5
輸出:30
max_count:32
*/
可以看出這種遞迴的做法,程式的執行複雜度還是比較高的當層數遞增的時候,2
n2^n
2n是乙個超大數量級的任務。
從上面我們其實可以發現,中間有大量的重複計算,比如第四層到第五層的7->5這個計算,每次到7的時候都會進行一次計算,就會重複。所以,解決的辦法是,把中間的計算結果儲存下來就好。
把中間結果儲存下來,我們也需要逆向思考,儲存的過程中需要從尾部開始儲存,這樣可以保證計算得到的結果是最大的。
2 7 4 4
4 5 2 6 5
這裡可以儲存第四層的結果,給第三層使用。比如,2+4=6 < 2+5=7 此時在第四層2的位置儲存7就好,第三層遍歷到此處時,可以直接取出7,就避免了重複計算。
這樣的複雜度的計算就會變成加法,第四層到第五層的計算次數,2 * 4 =8 第三層到第四層的計算次數 2 * 3 = 6 ,同理全部的計算次數8 + 6 + 4 + 2=20,計算次數明顯減少,當資料層數增加時,計算的複雜度也僅僅是一加法的形式增加,而不是以次冪的形式增加。
#include #include #include #include #include using namespace std;
#define max 101
int d[max][max];
int maxsum[max][max];
int n;
int max_count = 1;
int maxsum(int i, int j)
if(i == n)
else
return maxsum[i][j];
}int main()
}cout << maxsum(1, 1) << endl;
cout << "max_count:" << max_count << endl;
return 0;
}/*輸出
30max_count:22
*/
把遞迴改為遞推,一般情況下都可以減少程式執行記憶體和執行時間。但是其思想就是剛剛討論的,逆推整個過程,達到冬天解決的目的。我們定義乙個maxsum儲存每一層正確的結果,不需要的就可以拋棄掉。
此時的複雜度計算,是每一層的個數4 + 3 + 2 + 1 = 10,少了遞迴的推進,我們可以不用遞迴到最後一層。
#include #include #include #include #include using namespace std;
#define max 101
int d[max][max];
int *maxsum;
int n;
int max_count = 1;
int main()
}maxsum = d[n];
for(int i = n-1; i >= 1;i--)
}cout << "sum: " 《很多問題都可以用遞迴的方法解決,其思想就是將很大的問題進行分解成很多的小問題,然後解決掉小問題,拼在一起就是整個問題的解決辦法。
當然這僅僅是乙個很小的問題,複雜度較低。回頭我再研究乙個代數方程的例子。
動態規劃演算法
一 動態規劃演算法原理 將待求解的問題分解成若干個相互聯絡的子問題,先求解子問題,然後從這些子問題的解得到原問題的解 對於重複出現的子問題,只在第一次遇到的時候對它進行求解,並把答案儲存起來。了不去求解相同的子問題,引入乙個陣列,把所有子問題的解存於該陣列中,這就是動態規劃所採用的基本方法。動態規劃...
動態規劃演算法
動態規劃 通過把原問題分解為相對簡單的子問題來求解複雜問題。動態規劃常常適用於有重疊子問題和最優子結構性質的問題。演算法總體思想 演算法的基本步驟 演算法的基本要素 最優子結構 重疊子問題 備忘錄方法 問題描述 子串行 公共子串行 最長公共子串行 lcs 問題 問題分析 動態規劃求解lcs問題 最長...
動態規劃演算法
動態規劃演算法的思路 動態規劃法即 dynamic programming method dp 是系統分析中的種常用方法。動態規劃法是20世紀50年代由貝爾曼 r.bellman 等人提出的,用來解決多階段決策過程問題的一種最優化方法。多階段決策過程是指把研究問題分成若干個相互聯絡的階段,由每個階段...