題目
2
3 4
6 5 7
4 1 8 3
如上所示,以上三角形由一連串的數字構成,要求從頂點 2 開始走到最底下邊的最短路徑,
每次只能向當前節點下面的兩個節點走,如 3 可以向 6 或 5 走,不能直接走到 7。
條件
三角形:一連串數字組成(用二維陣列儲存)
限制:只能向當前節點的下面兩個節點走
動態規劃問題建模階段
設三角形值為 value[ [2], [3,4], [6,5,7], [4,1,8,3] ]
底層 | 4 1 8 3
倒數第2層 | 7 6 10
倒數第3層 | 9 10
頂層 | 11
規律:
底層:一開始都是最小
倒數第二層:min(6+4, 6+1)=7、min(5+1, 5+8)=6、min(7+8,7+3)=10
倒數第三層:min(3+7, 3+6)=9、min(4+6, 4+10)=10
頂層:min(2+9, 2+10)=11
由此可見,只需要儲存前面的最小路徑數,就可推出後面的最小路徑數
動態規劃三個重要的概念
最優子結構:
由於有兩種走法,所以2往下走有兩種方案(選最小值)
2往下走 = min( 2+3, 2+4 )
邊界:
最底層 4,1,8,3 是最小的
轉態轉移公式:
d[i,j] = min(d[i+1,j], d[i+1,j+1]) + value[i,j]
(例:d[2,0] = min(d[3,0],d[3,1]) + value[2,0],即 d[2,0]=min(4,1)+6=7)
動態規劃求解問題階段
<?php
namespace app\index\controller;
// 動態規劃求解問題階段:
class Index
{
/**
* 動態規劃(Dynamic Programming)
* 時間複雜度:O(n)
* 空間複雜度:O(n)
*/
public function test()
{
$value = [
[2],
[3,4],
[6,5,7],
[4,1,8,3]
];
$value_len = count($value); // 三角形的層數
$min = $value[$value_len-1]; // 初始值為陣列底層值
// 迴圈三角形陣列,自底向上,從倒數第二層開始
for ($i = $value_len - 2; $i >= 0; $i--) {
$sub_len = count($value[$i]); // 每層的長度
// 迴圈每層的數字,從左到右
for ($j = 0; $j < $sub_len; $j++) {
$min[$j] = min($min[$j], $min[$j + 1]) + $value[$i][$j];
}
}
echo $min[0];
}
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結