DP問題練習1:數字三角最短路徑問題

DP問題練習1:數字三角最短路徑問題

問題描述

給定一個數字三角形,找到從頂部到底部的最小路徑和。每一步能夠移動到下面一行的相鄰數字上。javascript

樣例:

好比,給出下列數字三角形:java

2
    3 4
   6 5 7
  4 1 8 3

從頂到底部的最小路徑和爲11 ( 2 + 3 + 5 + 1 = 11)。數組

思路

咱們給每個位置標上座標
     2       (0,0)
    3 4   (1,0) (1,1)
   6 5 7      ...
  4 1 8 3     ...
  咱們用f(i,j)表示從(i,j)位置一直到三角形底部的最小路徑和。
  那麼f(0,0) = min(f(1,0),f(1,1))+Value(0,0); Value(0,0)就是值2
  f(1,0) = min(f(2,0),f(2,1))+Value(1,0);
   ...
  1.推導出狀態轉移方程:
  f(i,j) = min(f(i+1,j),f(i+1,j+1)) + Value(i,j)。
  利用這個狀態轉移方程咱們能夠寫出一個遞歸函數。
  2.遞歸的邊界肯定:
  對於f(i,j),當:
  i == 三角形高度-1 的時候,直接返回Value(i,j)

代碼:

(function(){
    main();
})();
/**
 * [三角問題最小路徑和]
 * @param  {[Array]} triangleList [trianglelist]
 * @return {[Number]} [length of minimumTotal]
 */
function minimumTotal(triangleList){
  //這個DP問題的狀態轉移方程
  //f(i,j) = min(f(i+1,j),f(i+1,j+1))+(i,j)  f(i,j)表示當前步驟(i,j)走到最後,所對應的最小路徑和
  var triangleHeight = getTriangleHeight(triangleList);

  function calResult(i,j){
    if(i == triangleHeight-1){
        return triangleList[getIndex_i(i)+j];
    }else{
        var res1 = calResult(i+1,j);
        var res2 = calResult(i+1,j+1);
        return Math.min(res1,res2)+triangleList[getIndex_i(i)+j];
    }
  }
  return calResult(0,0);                                                                 }
/**
 * 獲取三角形有多少行
 * @param  {[Array]} triangleList [description]
 * @return {[Number]}              [description]
 */
function getTriangleHeight(triangleList){
    var height = 0.5*(Math.sqrt(1+triangleList.length*8)-1);
    console.assert(parseInt(height) == height,"輸入的三角形數據數量有誤");
    return height;
}
/**
 * 經過行數獲取該行第一個元素在數組中的下標
 * @param  {[Number]} lineNo [行標,從0開始計]
 * @return {[Number]}        [數組下標]
 */
function getIndex_i(lineNo){
    // if(lineNo == 0)
    //     return 0;
    // return getIndex_i(lineNo-1)+lineNo;
    //根據 f(n) = f(n-1)+n; f(0)=0 推到 f(n) = n(n+1)/2
    return lineNo*(lineNo+1)/2;
}

function main(){
    var TEMP = [2,3,4,6,5,7,4,1,8,9];
    console.log(minimumTotal(TEMP))
}
相關文章
相關標籤/搜索