leetcode 1039. 多边形三角剖分的最低得分

题目链接:力扣

你有一个凸的 n 边形,其每个顶点都有一个整数值。给定一个整数数组 values ,其中 values[i] 是第 i 个顶点的值(即 顺时针顺序 )。

假设将多边形 剖分 为 n - 2 个三角形。对于每个三角形,该三角形的值是顶点标记的乘积,三角剖分的分数是进行三角剖分后所有 n - 2 个三角形的值之和。

返回 多边形进行三角剖分后可以得到的最低分 。
 

示例 1:

输入:values = [1,2,3]
输出:6
解释:多边形已经三角化,唯一三角形的分数为 6。

示例 2:

输入:values = [3,7,4,5]
输出:144
解释:有两种三角剖分,可能得分分别为:3*7*5 + 4*5*7 = 245,或 3*4*5 + 3*4*7 = 144。最低分数为 144。

示例 3:

输入:values = [1,3,1,4,1,5]
输出:13
解释:最低分数三角剖分的得分情况为 1*1*3 + 1*1*4 + 1*1*5 + 1*1*1 = 13。

提示:

  • n == values.length
  • 3 <= n <= 50
  • 1 <= values[i] <= 100

官方题解注释

class Solution {
public:
    int minScoreTriangulation(vector<int>& values) {
        // 记忆化存储已经计算过的子问题的解
        unordered_map<int, int> memo;
        int n = values.size();

        // 定义 dp 函数
        function<int(int, int)> dp = [&](int i, int j) -> int {
            // 三角形的边长小于 3,不需要划分,返回 0
            if (i + 2 > j) {
                return 0;
            }
            // 三角形的边长等于 3,只有一个三角形,返回这个三角形的分数
            if (i + 2 == j) {
                return values[i] * values[i + 1] * values[j];
            }
            // 计算 memo 的 key
            int key = i * n + j;
            // 如果当前子问题的解没有计算过
            if (!memo.count(key)) {
                int minScore = INT_MAX;
                // 枚举划分位置 k,计算每种划分方式的分数,取最小值
                for (int k = i + 1; k < j; k++) {
                    minScore = min(minScore, values[i] * values[k] * values[j] + dp(i, k) + dp(k, j));
                }
                // 存储当前子问题的解
                memo[key] = minScore;
            }
            // 返回当前子问题的解
            return memo[key];
        };
        // 返回最终问题的解
        return dp(0, n - 1);
    }
};

ChatGPT题解注释版

class Solution {
public:
    int minScoreTriangulation(vector<int>& values) {
        int n = values.size();
        // dp[i][j]表示从第i个点到第j个点所需的最小分数
        vector<vector<int>> dp(n, vector<int>(n));
        // 遍历区间长度
        for (int len = 3; len <= n; len++) {
            // 遍历区间起点
            for (int i = 0; i + len - 1 < n; i++) {
                // 区间终点
                int j = i + len - 1;
                // 初始化dp[i][j]
                dp[i][j] = INT_MAX;
                // 遍历区间中间点
                for (int k = i + 1; k < j; k++) {
                    // 求解dp[i][j]
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + values[i] * values[j] * values[k]);
                }
            }
        }
        // dp[0][n-1]即为答案
        return dp[0][n - 1];
    }
};

unordered_map<int, int>

unordered_map<int, int> 是 C++ STL(标准模板库)中的一个关联容器,它可以将一组键值对映射到唯一的值。在这个特定的代码中, unordered_map<int, int> memo; 用来存储已经计算过的结果以便后续使用,避免了重复计算,从而提高了代码的效率。

vector<int>&

vector<int>& 表示一个引用,它用于将一个 vector<int> 类型的变量作为函数的参数,以便在函数中直接修改该变量,而不是创建一个新的副本。通过使用引用,可以避免在函数中复制大量数据,从而提高程序的效率。同时,引用还可以用于将函数的返回值传递给调用方。

function<int(int, int)> dp = [&](int i, int j) -> int

这句代码使用了lambda表达式,其结构如下:

[&](int i, int j) -> int {
    // 函数体
    return 0;
}

其中 & 表示使用lambda表达式所在作用域的变量,int i, int j 表示参数列表,-> int 表示返回值类型为 int。这样就定义了一个返回值为 int,带两个整型参数的lambda函数。

在本题中,这个lambda函数被用作动态规划函数,用于计算从第 i 个点到第 j 个点所需的最小得分。

猜你喜欢

转载自blog.csdn.net/qq_40016005/article/details/129919267