經典例題:洛谷p1216 數字三角形
寫乙個程式來查詢從最高點到底部任意處結束的路徑,使路徑經過數字的和最大。
每一步可以走到左下方的點也可以到達右下方的點。
下圖的黑色三角形是我們記憶化搜尋的路徑,我們想想,是不是可以不通過記憶化搜尋就能得到這個黑色三角形??
最優性:設走到某乙個位置的時候,它達到了路徑最大值,那麼在這之前,它走的每一步都是最大值。
-考慮這條最優的路徑:每一步均達到了最大值
最優性的好處:要達到乙個位置的最優值,它的前一步也一定是最優的。
-考慮圖中位置,如果它要到達最優值,有兩個選擇,從左上方或者右上方的最優值得到:
所以從這裡,定義動態規劃(dp):只記錄狀態的最優值,並用最優值來推導出其他的最優值。
記錄 f[i][j] 為第 i 行第 j 列的路徑最大值,有兩種方法可以推導:(兩個分支兩種狀態,選取最大)
@逆推:用 f[i-1][j],f[i-1][j-1] 來計算 f[i][j]。用前面的來計算當前項。「從什麼狀態可以到達我這裡」(還沒想好誰到誰)
這兩種思考方法也是動態規劃中最基本的兩種方法,解決絕大部分dp我們都可以採用這樣的方法。
//t2:數字金字塔-順推(有點類似於記憶化搜尋的思路)
//d陣列儲存順序:記錄從頂端向底部走的路徑最優值(自頂向下)
#include#includeusing namespace std;
int a[1005][1005];//儲存數塔
int d[1005][1005];//從該點到底端的最大數字和
int main()
d[0][0]=a[0][0];
for(int i=0;i#includeusing namespace std;
int a[1005][1005];//儲存數塔
int d[1005][1005];//從該點到底端的最大數字和
int main()
//逆推(自頂向下)
*轉移方程:最優值之間的推導公式。
@順推:
f[i+1][j] = max (f[i][j] + a[i+1][j]);
f[i+1][j+1] = max (f[i][j] + a[i+1][j+1]);
@ 逆推:
f[i][j] = max (f[i-1][j], f[i-1][j-1]) + a[i][j]; (注意!逆推時要注意邊界情況! )
順推和逆推本質上是一樣的(複雜度一致);順推和搜尋的順序類似;
而逆推則是將順序反過來;順推考慮的是「我這個狀態的下一步去**」 ,逆推的考慮的是「從什麼狀態可以到達我這裡」 。
同時在轉移的過程中我們要時刻注意邊界情況。
我們還可以改變搜尋順序為自底向上(下面這兩個演算法基本一樣,寫法不一樣):
//數字金字塔-逆推
//改變順序:記錄從底部向上走的路徑最優值(自底向上)
//和之前的逆推區別:這樣較自頂向下不需要判斷邊界,更加簡單
#include#includeusing namespace std;
int a[1005][1005];//儲存數塔
int d[1005][1005];//從該點到底端的最大數字和
int main()
d[0][0]=a[0][0];
for(int j=0;j=0;i--)
for(int j=0;j<=i;j++)
d[i][j]=a[i][j]+max(d[i+1][j+1],d[i+1][j]);//當前的+當前[i][j]左下方和右下方取較大
//答案在金字塔頂端
ans=d[0][0];
cout
int a[1005][1005];
int d[1005][1005];
int i,j,n,t;
int dp(int i,int j) }
int main()
// 兩種輸出方式
// dp(0,0);
// cout
乙個小問題:在數字金字塔中,為什麼能夠使用動態規劃 呢??答:因為有明確的順序: 自上而下 ,也就是說,能劃分成不同的階段,這個階段是逐步進行的,這和搜尋順序也是類似的,所以,只要劃分好階段, 從前往後推,與從後往前推都是可以的
洛谷1216 數字三角形
題目描述 觀察下面的數字金字塔。寫乙個程式來查詢從最高點到底部任意處結束的路徑,使路徑經過數字的和最大。每一步可以走到左下方的點也可以到達右下方的點。7 3 8 8 1 02 7 4 4 4 5 2 6 5 在上面的樣例中,從7 到 3 到 8 到 7 到 5 的路徑產生了最大 輸入輸出格式 輸入格...
洛谷 P1216 數字三角形(dp)
題目描述 觀察下面的數字金字塔。寫乙個程式來查詢從最高點到底部任意處結束的路徑,使路徑經過數字的和最大。每一步可以走到左下方的點也可以到達右下方的點。輸入輸出格式 輸入格式 第乙個行包含 r 1 r 1000 表示行的數目。後面每行為這個數字金字塔特定行包含的整數。所有的被 的整數是非負的且不大於1...
洛谷 P1216數字三角形
題目描述 觀察下面的數字金字塔。寫乙個程式來查詢從最高點到底部任意處結束的路徑,使路徑經過數字的和最大。每一步可以走到左下方的點也可以到達右下方的點。在上面的樣例中,從7 3 8 7 5 的路徑產生了最大 輸入格式 第乙個行乙個正整數 rr 表示行的數目。後面每行為這個數字金字塔特定行包含的整數。輸...