下圖給出了乙個數字三角形,請編寫乙個程式,計算從頂至底的某處的一條路徑,使該路徑所經過的數字的總和最大。
(1)每一步可沿左斜線向下或右斜線向下
(2)1 < 三角形行數 < 100
(3)三角形數字為0,1,…99
有很多個測試案例,對於每乙個測試案例, 通過鍵盤逐行輸入,第1行是輸入整數(如果該整數是0,就表示結束,不需要再處理),表示三角形行數n,然後是n行數
輸出最大值。
5
73 8
8 1 0
2 7 4 4
4 5 2 6 5
30
用二維陣列存放數字三角形。
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)
遞迴求解,會嚴重超時,因為出現重複計算,如下圖所示。深度遍歷每條路徑,存在大量重複計算。5行的總時間為:1+#include
#include
#define max 101
using
namespace
std;
int d[max][max];
int num;
int maxsum(int i, int j)
int main(int argc, char
const *argv)
2+4+
8+16=
31=25
−1則時間複雜度為 2n
第一次計算maxsum(r,j)值的時候,儲存下來,下次需要的時候,直接取出計算,這樣就避免了重複計算。時間複雜度為o(
n2) ,因為三角形的數字總和為n(
n+1)/2。
從底向上遞推,出最後一行外,每一行的每個點的最大值等於自身加上下面一行對應左右兩個點的最大值,從下往上遞推,最頂部的即所求。比如下圖所示。首先最後一行的最大值就是它本身。倒數第二行第乙個數7就是輸入的倒二行的第乙個數2 + 4 和 2 +5 取最大值 。逐步遞推到頂部。#include
#include
#include "string.h"
#define max 101
using
namespace
std;
int d[max][max];
int max_sum_arr[max][max];
int num;
int maxsum(int i, int j)
return max_sum_arr[i][j];
}int main(int argc, char
const *argv)
在用動態規劃解題時,我們往往將和子問題相關的各個變數的一組取值,稱之為乙個「狀態」。乙個「狀態」對應於乙個或多個子問題,所謂某個「狀態」下的「值」,就是這個「狀態」所對應的子問題的解。
以「數字三角形」為例,初始狀態就是底邊數字,值就是底邊數字值。
定義出什麼是「狀態」,以及在該 「狀態」下的「值」後,就要找出不同的狀態之間如何遷移――即如何從乙個或多個「值」已知的「狀態」,求出另乙個「狀態」的「值」 。狀態的遷移可以用遞推公式表示,此遞推公式也可被稱作「狀態轉移方程」。
問題具有最優子結構性質。如果問題的最優解所包含的子問題的解也是最優的,我們就稱該問題具有最優子結構性質。
無後效性。當前的若干個狀態值一旦確定,則此後過程的演變就只和這若干個狀態的值有關,和之前是採取哪種手段或經過哪條路徑演變到當前的這若干個狀態,沒有關係。
動態規劃 基礎題 數字三角
數字三角形 問題描述 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 上圖給出了乙個數字三角形。從三角形的頂部到底部有很多條不同的路徑。對於每條路 徑,把路徑上面的數加起來可以得到乙個和,和最大的路徑稱為最佳路徑。你的任務就是求 出最佳路徑上的數字之和。輸入資料 輸入的第一行是乙個整數 ...
動態規劃入門 數字三角形
給定乙個由n行數字組成的數字三角形,如下圖所示 從上到下最大的值的總和。這道題在動態規劃裡是入門級的題目,運用到了遞迴。對於這道題共有兩個思路,第一種是從上向下推,第二種是從下向上推。先從第一種分析。我們設這個二維陣列為dp,在推導的時候我們先把遞的公式寫出來,從上向下退的話,zui a i j m...
動態規劃之數字三角形問題
數字三角形問題 time limit 1000 ms memory limit 65536 kib submit statistic discuss problem description 給定乙個由n行數字組成的數字三角形如下圖所示。試設計乙個演算法,計算出從三角形的頂至底的一條路徑,使該路徑經過...