【动态规划】Lintcode 109. 数字三角形

109. 数字三角形

题目描述:给定一个数字三角形,找到从顶部到底部的最小路径和。每一步可以移动到下面一行的相邻数字上。
在这里插入图片描述
本题可以作为动态规划的题目入门。为了深刻理解,这里使用3种方法实现:

  1. 记忆化搜索(Divide Conquer + Memorize)
  2. 动态规划(自底向上)
  3. 动态规划(自顶向下)
// 1. 记忆化搜索(Divide Conquer + Memorize)
class Solution {
    
    
public:
    /**
     * @param triangle: a list of lists of integers
     * @return: An integer, minimum path sum
     */
    int minimumTotal(vector<vector<int>> &triangle) {
    
    
        if (triangle.empty() || triangle[0].empty()) {
    
    
            return 0;
        }
        
        int rows = triangle.size();//行数
        int lastRow_cols = triangle[rows - 1].size();//最后一行的列数
        vector<vector<int> > hash(rows, vector<int>(lastRow_cols, INT_MAX));
        
        return dfs(triangle, 0, 0, hash);
    }
    
    int dfs(vector<vector<int> > &triangle, int x, int y, vector<vector<int> > &hash) {
    
    
        if (x == triangle.size()) {
    
    
            return 0;
        }
        
        if (INT_MAX != hash[x][y]) {
    
    
            return hash[x][y];
        }
        
        int left = dfs(triangle, x + 1, y, hash);
        int right = dfs(triangle, x + 1, y + 1, hash);
        hash[x][y] = min(left, right) + triangle[x][y];
        return hash[x][y];
    }
};

// 2. 动态规划(自底向上)
class Solution {
    
    
public:
    /**
     * @param triangle: a list of lists of integers
     * @return: An integer, minimum path sum
     */
    int minimumTotal(vector<vector<int>> &triangle) {
    
    
        int n = triangle.size();//行数
        vector<vector<int>> f(n);//这一层每个点距离最底层的最小路径和
        
        //起始值
        for (int i = 0; i < triangle[n-1].size(); ++i) {
    
    
            f[n-1].push_back(triangle[n-1][i]);
        }
        
        //中间结果计算
        for (int j = n-2; j >= 0; --j) {
    
    
            for (int i = 0; i < triangle[j].size(); ++i) {
    
    
                f[j].push_back(min(f[j + 1][i], f[j + 1][i + 1]) + triangle[j][i]);
            }
        }
        
        return f[0][0];
    }
};

// 3. 动态规划(自顶向下)
class Solution {
    
    
public:
    /**
     * @param triangle: a list of lists of integers
     * @return: An integer, minimum path sum
     */
    int minimumTotal(vector<vector<int>> &triangle) {
    
    
        int n = triangle.size();//行数
        vector<vector<int> > f(n);//从顶部到当前节点的最短路径和
        //起始值
        f[0].push_back(triangle[0][0]);
        
        for (int i = 1; i < n; ++i) {
    
    
            for (int j = 0; j < triangle[i].size(); ++j) {
    
    
                //边界情况
                if (0 == j) {
    
    
                    f[i].push_back(f[i - 1][j] + triangle[i][j]);//左边界
                    continue;
                }
                if (triangle[i].size() - 1 == j) {
    
    
                    f[i].push_back(f[i - 1][j - 1] + triangle[i][j]);//右边界
                    continue;
                }
                //正常情况
                f[i].push_back(min(f[i - 1][j - 1], f[i - 1][j]) + triangle[i][j]);
            }
        }
        
        auto minSum = min_element(f[n-1].begin(), f[n-1].end());
        return *minSum;
    }
};

猜你喜欢

转载自blog.csdn.net/phdongou/article/details/113957796