問題描述:
有乙個有非負整數組成的三角形,第一行只有乙個數,除了最下行之外的每個數的左下方和右下方各有乙個數。如下圖:
從第一行的數字開始每次可以向左走或者向右走,直到走到最下行,把沿途經過的所有數字全部加起來,如何走才能使這個和最大?
1. 回溯法:可以求出所有的路線,然後從所有的路線中選擇最好的,但是效率太低。
2. 動態規劃:
1) 把當前的位置(i,j)看成乙個狀態,定義狀態(i,j)的指標函式d(i,j)為從(i,j)出發時能得到的最大和(包括(i,j)本身的值)。原問題的解是:d(1,1)。
2) 狀態轉移:d(i,j)=a(i,j)+max.
3) 遞迴程式實現:程式簡潔,但是效率低,因為存在大量重複計算的節點。
int solve(int i,int j)
return a[i][j]+(i==n? 0 : max(solve(i+1,j),solve(i+1,j+1)));
4) 遞推程式實現:時間複雜度為o(n^2),最下面一行單獨處理後,從下至上逆序列舉每一行。
int i,j;
for(j=1;j<=n;j++)
d[n][j]=a[n][j];
for(i=n-1;i>=1;i--)
for(j=1;j<=i;j++)
d[i][j]=a[i][j]+max(d[i+1][j],d[i+1][j+1]);//d[i+1][j],d[i+1][j+1]已經先於d[i][j]計算出
5) 記憶化搜尋:不必事先確定各狀態的計算順序,但需要記錄每個狀態「是否計算過」。
memset(d,-1,sizeof(d));
int solve(int i,int j)
if(d[i][j]>=0)
return d[i][j];
return d[i][j]=a[i][j]+(i==n ? 0 : max(solve(i+1,j), solve(i+1,j+1)) );
程式依然是遞迴的,但是能避免重複訪問節點。因為所有的數字非負,那麼已經算出的結點就應該是非負的,首先清空狀態函式為-1,若不小於0,那麼不用再計算。
動態規劃 數字三角形問題
數字三角形問題 time limit 1000ms memory limit 65536kb problem description 給定乙個由n行數字組成的數字三角形如下圖所示。試設計乙個演算法,計算出從三角形的頂至底的一條路徑,使該路徑經過的數字總和最大。對於給定的由n行數字組成的數字三角形,計...
動態規劃 數字三角形問題
有乙個由非負整數組成的三角形,第一行只有乙個數,除了最下行之外每個數的左下方和右下方各有乙個數.3 24 10 1 4 3 2 20 從第一行的數開始,每次可以往左下或右下走一格,直到走到最下行,把沿途經過的數全部加起來,如何走才能使得這個和盡量大?輸入 三角形的行數n,數字三角形的各個數 從上到下...
動態規劃 數字三角形問題
problem description 給定乙個由n行數字組成的數字三角形如下圖所示。試設計乙個演算法,計算出從三角形的頂至底的一條路徑,使該路徑經過的數字總和最大。對於給定的由n行數字組成的數字三角形,計算從三角形的頂至底的路徑經過的數字和的最大值。input 輸入資料的第1行是數字三角形的行數n...