數字三角形——簡單遞推dp
阿新 • • 發佈:2018-12-19
給定一個由 行數字組成的數字三角形如下圖所示。試設計一個演算法,計算出從三角形 的頂至底的一條路徑(每一步可沿左斜線向下或右斜線向下),使該路徑經過的數字總和最大
輸入樣例:
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
輸出樣例:
30
思路:很明顯是用dp來解決,很容易啟發對遞迴思想的理解 既然要求第一層到最後一層的最長路徑,那麼肯定要遍歷一遍,如果從 遍歷到(dfs),每一層的最優情況我們都無從得知,因為後面的影響因素我們都無法預測,那麼還有另一種方法:就是每一個點往下都只有兩種情況,如果把這兩種情況都記錄下來,很明顯最多有 種,非常複雜
所以這裡要換一種討論最優解的思路,如果從第 層遍歷到第 層,那麼我在遍歷的時候,通過比較儲存的值一定是從後往前的最優解! 那麼你可能會問,為什麼從前往後不能儲存最優解呢?因為從後往前是雙入口單出口,這一個出口就保證了答案的唯一性 而從前往後是單入口多出口,我們無法保證這多個出口哪一個才是最優解,如果直接將這兩個出口進行比較,只能保證是區域性最優,而不是全域性最優
換一種說法,從上到下的時候我們要把答案交給下一層解決、下一層不知道、只能交給下下一層解決,直到最後一層 而從下到上,我們已經知道了最後一層的解決辦法,返回上一層,上一層得到解決,返回上上一層,相當於dfs結束了返回的過程
這題是動態規劃最水的一題大概,但是回過頭來細細思考,還是溫故而知新
#include<bits/stdc++.h> using namespace std; typedef long long ll; int n, a[105][105], dp[105][105]; int main(){ scanf("%d", &n); for(int i=0; i<n; i++) for(int j=0; j<=i; j++) scanf("%d", &a[i][j]); for(int i=0; i<n; i++) dp[n-1][i] = a[n-1][i]; for(int i=n-1; i>0; i--) for(int j=0; j<i; j++){ dp[i-1][j] = max(dp[i-1][j], a[i-1][j] + dp[i][j]); dp[i-1][j] = max(dp[i-1][j], a[i-1][j] + dp[i][j+1]); } printf("%d\n", dp[0][0]); }