數字三角形(poj1163)
description
73 8
8 1 0
2 7 4 4
4 5 2 6 5
在上面的數字三角形中尋找一條從頂部到底邊的路徑,使得
路徑上所經過的數字之和最大。路徑上的每一步都只能往左下或
右下走。只需要求出這個最大和即可,不必給出具體路徑。
三角形的行數大於1小於等於100,數字為 0 - 99
輸入格式:
5 //三角形行數。下面是三角形
73 8
8 1 0
2 7 4 4
4 5 2 6 5
要求輸出最大和
sample output
30source
ioi 1994
解題思路:
用二維陣列存放數字三角形。
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)。故對於n行的三角形:
if ( r == n)
maxsum(r,j) = d(r,j)
else
maxsum( r, j) = max + d(r,j)
改進如果每算出乙個maxsum(r,j)就儲存起來,下次用
到其值的時候直接取用,則可免去重複計算。
遞迴轉成遞推
「人人為我」遞推型動歸 pascal**
1 //by lyltim2 3uses math;
4var
n,i,j:byte;
5 a:array[1..10,1..10]of
word;
6 f:array[1..10,1..10]of
word;
7begin
8 assign(input,'
tower.in
');reset(input);
9 assign(output,'
tower.out
');rewrite(output);
10readln(n);
11for i:=1
to n do
12begin
13for j:=1
to i do
14read(a[i,j]);
15readln;
16end
;17 fillchar(f,sizeof(f),0
);18
for i:=1
to n do f[n,i]:=a[n,i];
19for i:=n-1
downto1do
20for j:=1
to i do
21 f[i,j]:=max(f[i+1,j],f[i+1,j+1])+a[i,j];
22 writeln('
max=
',f[1,1
]);23
close(input);close(output);
24end.
空間優化
沒必要用二維maxsum陣列儲存每乙個maxsum(r,j),只要從底層一行行向上
遞推,那麼只要一維陣列maxsum[100]即可,即只要儲存一行的maxsum值就
可以。進一步考慮,連maxsum陣列都可以不要,直接用d的
第n行替代maxsum即可。
節省空間,時間複雜度不變
遞推+空間優化 c++**
1//by lyltim2//
2015.2.11
3 #include 4 #include 5
using
namespace
std;
6int
main()
7
遞迴到動規的一般轉化方法
遞迴函式有n個引數,就定義乙個n維的陣列,陣列
的下標是遞迴函式引數的取值範圍,陣列元素的值
是遞迴函式的返回值,這樣就可以從邊界值開始,
逐步填充陣列,相當於計算遞迴函式值的逆過程。
動規解題的一般思路
1. 將原問題分解為子問題
把原問題分解為若干個子問題,子問題和原問題形式相同
或類似,只不過規模變小了。子問題都解決,原問題即解
決(數字三角形例)。
子問題的解一旦求出就會被儲存,所以每個子問題只需求
解一次。
2. 確定狀態
在用動態規劃解題時,我們往往將和子問題相
關的各個變數的一組取值,稱之為乙個「狀
態」。乙個「狀態」對應於乙個或多個子問題,
所謂某個「狀態」下的「值」,就是這個「狀
態」所對應的子問題的解。
所有「狀態」的集合,構成問題的「狀態空間」。「狀態
空間」的大小,與用動態規劃解決問題的時間複雜度直接相關。
在數字三角形的例子裡,一共有n×(n+1)/2個數字,所以這個
問題的狀態空間裡一共就有n×(n+1)/2個狀態。
整個問題的時間複雜度是狀態數目乘以計算每個狀態所需
時間。在數字三角形裡每個「狀態」只需要經過一次,且在每個
狀態上作計算所花的時間都是和n無關的常數。
用動態規劃解題,經常碰到的情況是,k個整型變數能
構成乙個狀態(如數字三角形中的行號和列號這兩個變數
構成「狀態」)。如果這k個整型變數的取值範圍分別是
n1, n2, ……nk,那麼,我們就可以用乙個k維的陣列
array[n1] [n2]……[nk]來儲存各個狀態的「值」。這個
「值」未必就是乙個整數或浮點數,可能是需要乙個結構
才能表示的,那麼array就可以是乙個結構陣列。乙個
「狀態」下的「值」通常會是乙個或多個子問題的解。
3. 確定一些初始狀態(邊界狀態)的值
以「數字三角形」為例,初始狀態就是底邊數字,值
就是底邊數字值。
4. 確定狀態轉移方程
定義出什麼是「狀態」,以及在該 「狀態」下的「值」後,就要
找出不同的狀態之間如何遷移――即如何從乙個或多個「值」已知的
「狀態」,求出另乙個「狀態」的「值」(「人人為我」遞推型)。狀
態的遷移可以用遞推公式表示,此遞推公式也可被稱作「狀態轉移方
程」。能用動規解決的問題的特點
1) 問題具有最優子結構性質。如果問題的最優解所包含的
子問題的解也是最優的,我們就稱該問題具有最優子結
構性質。
2) 無後效性。當前的若干個狀態值一旦確定,則此後過程
的演變就只和這若干個狀態的值有關,和之前是採取哪
種手段或經過哪條路徑演變到當前的這若干個狀態,沒
有關係。
動態規劃入門 數字三角形
給定乙個由n行數字組成的數字三角形,如下圖所示 從上到下最大的值的總和。這道題在動態規劃裡是入門級的題目,運用到了遞迴。對於這道題共有兩個思路,第一種是從上向下推,第二種是從下向上推。先從第一種分析。我們設這個二維陣列為dp,在推導的時候我們先把遞的公式寫出來,從上向下退的話,zui a i j m...
數字三角形(動態規劃入門題)
題目描述 7 3 88 1 0 2 7 4 4 4 5 2 6 5 圖1 圖1給出了乙個數字三角形。從三角形的頂部到底部有很多條不同的路徑。對於每條路徑,把路徑上面的數加起來可以得到乙個和,你的任務就是找到最大的和。輸入的是一行是乙個整數n 1 n 100 給出三角形的行數。下面的n行給出數字三角形...
動態規劃入門1 數字三角形 C
作為乙個菜雞,研究了幾天的dp,把經典例題研究了幾遍,現在,我在這發表一下自己的菜雞見解,記錄下我對dp的理解。dp裡面少不了遞迴,當然也能混在搜尋裡面構成記憶化搜尋作為優化,也可以用遞推來動態規劃。具體你要我說動態規劃是個什麼東西,我也只能說說自己的理解 滿足條件 綜上,這個動態規劃很重要的就是記...