1. 程式人生 > >動態規劃之從搜尋到記憶化搜尋到遞推式

動態規劃之從搜尋到記憶化搜尋到遞推式

120. Triangle

Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.

For example, given the following triangle

[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]

The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1

 = 11).

//divided and conquer
class Solution{
    public int minimumTotal(List<List<Integer>> triangle){
        return helper(triangle,0,0);
    }
    public int helper(List<List<Integer>> triangle,int x,int y){
        if(x == triangle.size()) return 0;
        int left = helper(triangle,x+1,y);
        int right = helper(triangle,x+1,y+1);
        return triangle.get(x).get(y)+Math.min(left,right);
    }
}

//divided and conquer + memory
class Solution{
    public int[][] memory;
    public int minimumTotal(List<List<Integer>> triangle){
        memory = new int[triangle.size()][triangle.size()];
        for(int i = 0; i < memory.length; i++){
            Arrays.fill(memory[i],Integer.MAX_VALUE);
        }
        return helper(triangle,0,0);
    }
    public int helper(List<List<Integer>> triangle,int x,int y){
        if(x == triangle.size()) return 0;
        if(memory[x][y] != Integer.MAX_VALUE) return memory[x][y];
        int left = helper(triangle,x+1,y);
        int right = helper(triangle,x+1,y+1);
        memory[x][y] = triangle.get(x).get(y)+Math.min(left,right);
        return memory[x][y];
    }
}

//DP bottom-up
class Solution{
    public int minimumTotal(List<List<Integer>> triangle){
        if(triangle == null || triangle.get(0).size() == 0)
            return -1;
        if(triangle.get(0) == null || triangle.get(0).size() == 0)
            return -1;
        int m = triangle.size();
        int[][] dp = new int[m][m];//表示從(i,j)出發到最後一層的最小路徑長度
        //先初始化最底層的值
        for(int i = 0;i < m; i++){
            dp[m-1][i] = triangle.get(m-1).get(i);
        }
        for(int i = m-2; i >= 0; i--){
            for(int j = 0;  <= i; j++){
                dp[i][j] = triangle.get(i).get(j) + Math.min(dp[i+1][j],dp[i+1][j+1]);
            }
        }
        return dp[0][0];
    }
    
// }
//DP top-down
/*
state:dp[i][j] 表示從(0,0)出發到(i,j)的最小路徑長度
function:min(dp[i-1][j],dp[i-1][j-1])+triangle[i][j]
intialize:dp[0][0] = triangle[0][0] for(i=1->m-1) dp[i][0] = dp[i-1][0] + triangle[i][0] dp[i][i] = dp[i-1][i-1]+triangle[i][i]
answer:min(dp[m-1][i]) for i=0->m-1    
*/ 
class Solution{
    public int minimumTotal(List<List<Integer>> triangle){
        if(triangle == null || triangle.get(0).size() == 0)
            return -1;
        if(triangle.get(0) == null || triangle.get(0).size() == 0)
            return -1;
        int m = triangle.size();
        int[][] dp = new int[m][m];
        dp[0][0] = triangle.get(0).get(0);
        //初始化邊界值
        for(int i = 1; i < m;i++){
            dp[i][0] = dp[i-1][0] + triangle.get(i).get(0);//左邊界初始化
            dp[i][i] = dp[i-1][i-1]+triangle.get(i).get(i);//右邊界初始化
        }
        for(int i = 1; i < m; i++){
            for(int j = 1; j < i; j++){
                dp[i][j] = Math.min(dp[i-1][j],dp[i-1][j-1]) + triangle.get(i).get(j);
            }
        }
        //遍歷最後一層,取出最小值
        int minValue = Integer.MAX_VALUE;
        for(int i = 0; i < m; i++)
            minValue = Math.min(minValue,dp[m-1][i]);
        return minValue;
    }
    
}