0
点赞
收藏
分享

微信扫一扫

牛客网 -- CC31 三角形


CC31 三角形

给出一个三角形,计算从三角形顶部到底部的最小路径和,每一步都可以移动到下面一行相邻的数字,例如,给出的三角形如下:

[[20],[30,40],[60,50,70],[40,10,80,30]]

最小的从顶部到底部的路径和是20 + 30 + 50 + 10 = 110。

注意:

如果你能只用O(N)的额外的空间来完成这项工作的话,就可以得到附加分,其中N是三角形中的行总数。

试题链接CC31 三角形

解题思路,动态规划,下面分为两种思想

  • 状态定义 F[i][j] 从最顶层到当前位置最短路径和
  • 状态方程 F[i][j] = min(F[i-1][j], F[i-1][j-1]) + arr[i][j]
  • 初始化 F[0][0] = arr[0][0]

注意,对与我们当前点只能通过两种方式到达,因此我们需要判断我们上面一层的左侧是否存在元素,这点很重要

牛客网 -- CC31 三角形_动态规划

还要考虑一个问题,我们的状态定义的是从最上层到当前位置的最小路径和,也就是我们到达最后一层会出现很多个和,我们要看他们的最小值.

class Solution
{
public:
  /// @brief 自上向下  这道题连题目都没有说清楚,线下的时候只能 垂直和右下
  /// @param triangle
  /// @return
  int minimumTotal(vector<vector<int>> &triangle)
  {
    if (triangle.empty())
      return -2;
    vector<vector<int>> dp(triangle.size());
    for (int i = 0; i < triangle.size(); ++i)
    {

      vector<int> v(i + 1, -1);
      dp[i] = v;
    }

    dp[0][0] = triangle[0][0];

    for (int i = 1; i < triangle.size(); i++)
    {
      for (int j = 0; j < triangle[i].size(); j++)
      {
        if (j != 0 && i == j)
        {
          dp[i][j] = triangle[i][j] + dp[i - 1][j - 1];
          continue;
        }

        int minNum = dp[i - 1][j];
        if (j - 1 >= 0)
        {
          minNum = min(minNum, dp[i - 1][j - 1]);
        }

        dp[i][j] = minNum + triangle[i][j];
      }
    }

    // 找最小值
    int result = dp[triangle.size() - 1][0];
    for (int i = 1; i < dp[triangle.size() - 1].size(); ++i)
    {
      if (result > dp[triangle.size() - 1][i])
        result = dp[triangle.size() - 1][i];
    }
    return result;
  }
};

现在来是从下往上,这里我们也是动态规划

  • 状态定义 F[i][j] : 表示从最底层到当前位置的最短路径和
  • 状态方程 F[i][j] = min(F[i+1][j], F[i+1][j+1]) + arr[i][j]
  • 初始化 最后一行都要初始化

这里要注意我们当前位置从下层只能从下层和下层的右边一个拿到,我们要的结果就是F[0][0]

牛客网 -- CC31 三角形_初始化_02

class Solution {
public:
    int minimumTotal(vector<vector<int> >& triangle) {
        if (triangle.empty())
            return -1;
        std::vector<std::vector<int>> dp(triangle.size());
        for (int i = 0; i < triangle.size(); i++)
        {
            std::vector<int> v(i + 1, -1);
            dp[i] = v;
        }

        // 初始化
        for (int i = 0; i < triangle.back().size(); i++)
        {
            dp[triangle.size() - 1][i] = triangle[triangle.size() - 1][i];
        }

        // 开始动归
        for (int i = (int)triangle.size() - 1 - 1; i >= 0; i--)
        {
            for (int j = 0; j < triangle[i].size(); j++)
            {
                dp[i][j] = std::min(dp[i + 1][j], dp[i + 1][j + 1]) + triangle[i][j];
            }
        }

        return dp[0][0];
    }
};

牛客网 -- CC31 三角形_i++_03


举报

相关推荐

0 条评论