动态规划习题--九章算法第五、六章习题

1.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).

//如果最终最优路径过该点,从起点到该点的路径中,一定是最优的那条入选最优路径;但是从起点到该点的最优路径不一定是局部最优路径,有可能比同阶段的相邻点大
public class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        int n = triangle.size();
        int[][] f = new int[n][n];   //因为每步只能走临近的数字,因此横向最长也是跟行数相等
         
        //初始化
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                f[i][j]=Integer.MAX_VALUE;
            }
        }
        f[0][0]=triangle.get(0).get(0);
        //让f[i][j]代表从起点到i,j点的最小路径
        //最小路径和f[0][n-1]~f[n-1][n-1]的最小值
        for(int i =1;i<n;i++){
            for(int j=0;j<=i;j++){
                if(j==0)
                    f[i][j]=f[i-1][j]+triangle.get(i).get(j);
                else
                    f[i][j]=Math.min(f[i-1][j],f[i-1][j-1])+triangle.get(i).get(j);
            }
        }
        int min=Integer.MAX_VALUE;
        for(int i =0;i<n;i++){
            if(f[n-1][i]<min)
            min=f[n-1][i];
        }
        return min;
    }
}

精简空间度的版本:由于f[i][j]只与f[i-1][j]和f[i-1][j-1]有关,即仅与上一行状态有关因此可仅申请2行的空间,i的处理上%2就好了。如果与前2行有关就%3,....以此类推

 1 public class Solution {
 2     public int minimumTotal(List<List<Integer>> triangle) {
 3         int n = triangle.size();
 4         int[][] f = new int[2][n];   //因为每步只能走临近的数字,因此横向最长也是跟行数相等
 5          
 6         //初始化
 7         for(int i=0;i<n;i++){
 8             for(int j=0;j<n;j++){
 9                 f[i%2][j]=Integer.MAX_VALUE;
10             }
11         }
12         f[0][0]=triangle.get(0).get(0);
13         //让f[i][j]代表从起点到i,j点的最小路径
14         //最小路径和f[0][n-1]~f[n-1][n-1]的最小值
15         for(int i =1;i<n;i++){
16             for(int j=0;j<=i;j++){
17                 if(j==0)
18                     f[i%2][j]=f[(i-1)%2][j]+triangle.get(i).get(j);
19                 else
20                     f[i%2][j]=Math.min(f[(i-1)%2][j],f[(i-1)%2][j-1])+triangle.get(i).get(j);
21             }
22         }
23         int min=Integer.MAX_VALUE;
24         for(int i =0;i<n;i++){
25             if(f[(n-1)%2][i]<min)
26             min=f[(n-1)%2][i];
27         }
28         return min;
29     }
30 }

//如果最终最优路径过该点,从起点到该点的路径中,一定是最优的那条入选最优路径;但是从起点到该点的最优路径不一定是局部最优路径,有可能比同阶段的相邻点大
public class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        int n = triangle.size();
        int[][] f = new int[2][n];   //因为每步只能走临近的数字,因此横向最长也是跟行数相等
         
        //初始化
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                f[i%2][j]=Integer.MAX_VALUE;
            }
        }
        f[0][0]=triangle.get(0).get(0);
        //让f[i][j]代表从起点到i,j点的最小路径
        //最小路径和f[0][n-1]~f[n-1][n-1]的最小值
        for(int i =1;i<n;i++){
            for(int j=0;j<=i;j++){
                if(j==0)
                    f[i%2][j]=f[(i-1)%2][j]+triangle.get(i).get(j);
                else
                    f[i%2][j]=Math.min(f[(i-1)%2][j],f[(i-1)%2][j-1])+triangle.get(i).get(j);
            }
        }
        int min=Integer.MAX_VALUE;
        for(int i =0;i<n;i++){
            if(f[(n-1)%2][i]<min)
            min=f[(n-1)%2][i];
        }
        return min;
    }
}

原文地址:https://www.cnblogs.com/LolaLiu/p/4510059.html