Leetcode 1039. ポリゴン三角形分割の最小スコア

トピックリンク:リトゥオ

n 各頂点に整数値を持つ凸多角形があります 。 が番目の頂点の値で  ある values 整数 の配列が与えられた場合 (つまり、時計回りの順序で )。values[i]i

多角形が 三角形 に 分割されているとn - 2します 。各三角形について、その三角形の値は頂点ラベルのであり、三角形分割スコアは n - 2 三角形分割後のすべての三角形の値の合計です。

三角測量後の多角形の最低スコアを返します  。
 

例 1:

入力:値 = [1,2,3]
出力: 6
説明:多角形は、一意の三角形のスコア 6 で三角形化されています。

例 2:

入力:値 = [3,7,4,5]
出力: 144
説明:可能なスコアを持つ 2 つの三角形分割があります: 3*7*5 + 4*5*7 = 245、または 3*4*5 + 3 *4*7 = 144。最低スコアは 144 です。

例 3:

入力:値 = [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

このコードはラムダ式を使用しており、その構造は次のとおりです。

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

このうち&、 はラムダ式が使用されるスコープ内の変数を表し、int i, int jパラメータ リストを表し、-> int戻り値の型を表しますintこれは、int2 つの整数パラメーターの戻り値を持つラムダ関数を定義します。

この問題では、このラムダ関数を動的計画法関数として使用して、i 番目のポイントから j 番目のポイントまでに必要な最小スコアを計算します。

おすすめ

転載: blog.csdn.net/qq_40016005/article/details/129919267