1. 程式人生 > >演算法學習之動態規劃--數字三角形最大路徑和

演算法學習之動態規劃--數字三角形最大路徑和

題目:

7 3  8 8  1  0 2  7  4  4 4  5  2  6  5

在上面的數字三角形中尋找一條從頂部到底邊的路徑,使得路徑上所經過的數字之和最大。路徑上的每一步都只能往左下或右下走。只需要求出這個最大和即可,不必給出具體路徑。三角形的行數大於1小於等於100,數字為 0 - 99。

輸入格式:
5//三角形行數。下面是三角形
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
要求輸出最大和

解題思路:
用二維陣列存放數字三角形。
D( r, j) : 第r行第 j 個數字(r,j從1開始算)
MaxSum(r, j) : 從D(r,j)到底邊的各條路徑中,最佳路徑的數字之和。
問題轉化為求 MaxSum(1,1),這是典型的遞迴問題。D(r, j)出發,下一步只能走D(r+1,j)或者D(r+1, j+1)。所以有了下面的第一種方法

方法一:遞迴求解

#include<iostream>
using namespace std;

const int maxn = 101;
int D[maxn][maxn];                  //儲存三角形中第i行第j列的數值,i、j均從1開始
int n;                              //三角形行數

int maxSum(int i, int j){           //從D(i,j)到底邊的各條路徑中,最佳路徑的數字之和。
    if(i == n)                      //D(i,j)就在三角形底邊上
        return D[i][j];
    int x = maxSum(i+1,j);
    int y = maxSum(i+1,j+1);
    return max(x,y)+D[i][j];        //D(i,j)到底邊最優解
}

int main(){
    cin >> n;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=i; j++)
            cin>>D[i][j];
    cout<<maxSum(1,1)<<endl;        //從三角形頂點到底邊最優解
    return 0;
}

這樣做會超時,因為有太多的重複計算。當時間複雜度為 2^n,對於 n = 100 行,肯定超時。

對第一種方法的改進:如果每算出一個MaxSum(r,j)就儲存起來,下次用到其值的時候直接取用,則可免去重複計算。那麼可以用O(n2)時間完成計算。因為三角形的數字總數是 n(n+1)/2。

方法二:記憶遞迴型動歸程式(對方法一的改進)

#include<iostream>
using namespace std;

const int maxn = 101;
int sum[maxn][maxn];                //儲存已經算出的maxSum值
int D[maxn][maxn];
int n;

int maxSum(int i, int j){           //從D(i,j)到底邊的各條路徑中,最佳路徑的數字之和。
    if(sum[i][j] != -1)             //此maxSum已算出過
        return sum[i][j];
    if(i == n)
        sum[i][j] = D[i][j];
    else{
        int x = maxSum(i+1,j);
        int y = maxSum(i+1,j+1);
        sum[i][j] = max(x,y)+D[i][j];
    }
    return sum[i][j];
}

int main(){
    cin >> n;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=i; j++){
            cin>>D[i][j];
            sum[i][j] = -1;         //均初始化為-1
        }
    cout<<maxSum(1,1)<<endl;
    return 0;
}

方法二就有點囉嗦,我們現在不用遞迴,直接用遞推,也即動態規劃。在此方法中,從最底層往上層一層一層遞推求出當前最優解。程式碼如下。

方法三:動態規劃

#include<iostream>
using namespace std;
const int maxn = 101;
int n;
int D[maxn][maxn];
int maxSum[maxn][maxn];         //從D(i,j)到底邊的各條路徑中,最佳路徑的數字之和。
int main(){
    cin >> n;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=i; j++)
            cin >> D[i][j];
    for(int i=1; i<=n; i++)
        maxSum[n][i] = D[n][i];
    for(int i=n-1; i>=1; i--)
        for(int j=1; j<=i; j++)
            maxSum[i][j] = max(maxSum[i+1][j],maxSum[i+1][j+1]) + D[i][j];
    cout << maxSum[1][1] <<endl;
    return 0;
}

在方法三種,我們用了二維陣列儲存當前最優解,但實際上往上層遞推求解的過程中,我們只會用到下一層的資料,之前的結果都沒有用處了。所以只要一維陣列maxSum[100]即可。進一步考慮,連maxSum陣列都可以不要,直接用D的第n行替代maxSum即可。得到如下方法。

方法四:動態規劃(二)   ( 推薦!)

#include<iostream>
using namespace std;
const int maxn = 101;
int n;
int D[maxn][maxn];
int main(){
    cin >> n;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=i; j++)
            cin >> D[i][j];
    int *maxSum = D[n];             //maxSum指向第n行,利用第n行的空間儲存結果
    for(int i=n-1; i>=1; i--)
        for(int j=1; j<=i; j++)
            maxSum[j] = max(maxSum[j],maxSum[j+1]) + D[i][j];
    cout << maxSum[1] <<endl;
    return 0;
}

相關推薦

演算法學習動態規劃--數字三角形路徑

題目: 7 3  8 8  1  0 2  7  4  4 4  5  2  6  5 在上面的數字三角形中尋找一條從頂部到底邊的路徑,使得路徑上所經過的數字之和最大。路徑上的每一步都只能往左下或右下走。只需要求出這個最大和即可,不必給出具體路徑。三角形的行數大於1小於

動態規劃——數字三角形

題目描述: 求數字三角形從頂層到底層的最大和,路徑抉擇時只能向下或向右下走。 本題中的數字三角形: 7 3,8 8,1,0 2,7,4,4 4,5,2,6,5 題解:若三角形為等腰三角形或其他形式

演算法學習動態規劃--長公共子序列

題目: 給出兩個字串,求出這樣的一個最長的公共子序列的長度:子序列中的每個字元都能在兩個原串中找到,而且每個字元的先後順序和原串中的先後順序一致。 Sample Input : abcfbc abfc

數字三角形路徑動態規劃

div 路徑和 image 動態 節點 spa 直接 .cn 一行 思路:自底向上求解,從倒數第二行開始,本行節點到最後一行的最小路徑和等於該節點的數據加上下面左右兩個數據中最小的一個。不使用額外空間,直接將最小路徑和存儲到原有的數組中。1 int minimumTota

演算法學習動態規劃(leetcode 85. Maximal Rectangle)

0x01題目 85. Maximal Rectangle Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's

『嗨威說』演算法設計與分析 - PTA 數字三角形 / 大子段 / 編輯距離問題(第三章上機實踐報告)

本文索引目錄: 一、PTA實驗報告題1 : 數字三角形   1.1  實踐題目   1.2  問題描述   1.3  演算法描述   1.4  演算法時間及空間複雜度分析 二、PTA實驗報告題2 : 最大子段和   2.1  實踐題目   2.2  問題描述   2.

#動態規劃 LeetCode 64 路徑

bsp length 位置 根據 說明 font span 輸入 思考 給定一個包含非負整數的 m x n 網格,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和為最小。 說明:每次只能向下或者向右移動一步。 示例: 輸入: [ [1,3,1], [1,5,1

動態規劃數字三角形值(一)(遞迴)

題目:數字三角形,形如          3      3      2   4     5     1 1    3     4     1 每個點只能選擇向左或向右走,取一條路徑,使得路徑上數字和最大。 無需求出路徑,求出最大值。 輸入n,和 n 行數字三角形 n<

[演算法學習筆記]動態規劃鋼條切割問題

問題描述 有一個長度為n的鋼條需要切割成短鋼條出售,長度不同的鋼條售價也不同,如下: 長度i 1 2 3 4 5 6 7 8 9 10 價格p[i] 1 5 8 9 10 1

動態規劃——求數字三角形優解路徑

給定一個由n行數字組成的數字三角形如下圖所示。試設計一個演算法,對於給定的由 n行數字組成的數字三角形, 計算從三角形的頂至底的路徑經過的數字和的最大值。 注意:對於第i層的第j個數字,其所在路徑的下一個數字只能是第i+1層的第j個或第j+1個數字。

動態規劃——數字三角形

-- 就是 程序 else 視頻 問題: 維數 技術 i+1 題目: (題目來源:中國大學Mooc,程序設計與算法(二)算法基礎視頻課程) 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 在上面的數字三角形中尋找一條從頂部到底邊的路徑

動態規劃-數字三角形問題

有一個由非負整陣列成的三角形,第一行只有一個數,除了最下行之外每個數的左下方和右下方各有一個數.     1    3 2  4 10 1 4 3 2 20 從第一行的數開始,每次可以往左下或右下走一格,直到走到最下

演算法動態規劃

含義     動態規劃(dynamic programming)是運籌學的一個分支,是求解決策過程(decision process)最優化的數學方法。 分類     動態規劃一般可分為線性動規,

29.動態規劃-三角形路徑-Leetcode 120(python)

問題描述及示例 給定一個三角形,找出自頂向下的最小路徑和。每一步只能移動到下一行中相鄰的結點上。 例如,給定三角形: [ [2], [3,4], [6,5,7], [4,1,8,3] ] 自頂向下的最小路徑和為 11(即,2 

【簡單】動態規劃數字三角形

例題一:數字三角形(POJ1163) The Triangle Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 8321 Accepted: 35029 Descri

演算法總結動態規劃(DP)

適用動態規劃的特點 所解決的問題是最優化問題。 所解決的問題具有“最優子結構”。可以建立一個遞推關係,使得n階段的問題,可以通過幾個k<n階段的低階子問題的最優解來求解。 具有“重疊子結構”的特點。即,求解低階子問題時存在重複計算。 詞典法 大家都知道,遞迴演算法一般都存在大量的重複計算,這會造成不

LeetCode-120.三角形路徑(相關話題:動態規劃

給定一個三角形,找出自頂向下的最小路徑和。每一步只能移動到下一行中相鄰的結點上。 例如,給定三角形: [ [2], [3,4], [6,5,7], [4,1,8,3] ] 自頂向下的最小路徑和為 11(即,2 + 3 + 5 + 1 = 11)。 說明:

演算法導論 動態規劃

作者:鄒祁峰 郵箱:[email protected] 日期:2014.03.07 18:00 轉載請註明來自"祁峰"的CSDN部落格 1 問題描述     現有兩條裝配線,Sij表示第i條上完成第j道工序的裝配站。汽車完成組裝需要依次完成1~n工序。請找出完

動態規劃 數字三角形

數字三角形 Poj 問題描述 上面給出了一個數字三角形。從三角形的頂部到底部有多條不同的路徑。對於每條路徑,把路徑上面的數字加起來可以得到一個和,累加和最大的路徑成為“最佳路徑”。題目的任務就是求出最佳路徑上的數字之和。 注意:路徑上的每一步只能從一個數走到下一層和它最近的左邊數或

codevs動態規劃 數字三角形

如圖所示的數字三角形,從頂部出發,在每一結點可以選擇向左走或得向右走,一直走到底層,要求找出一條路徑,使路徑上的值最大。 分析:超菜的一道倒推題(完全無腦==) 動態轉移方程:f[i,j]:=max(f[i+1,j],f[i+1,j+1])+f[i,j]; const