区间dp

[Algo] 区间dp

1. 让字符串成为回文串的最少插入次数

// 1. 让字符串成为回文串的最少插入次数
// https://leetcode.cn/problems/minimum-insertion-steps-to-make-a-string-palindrome/description/
int minInsertions(string s) {
    int n = s.length();
    vector<vector<int>> dp(n, vector<int>(n));
    for (int l = 0; l < n - 1; l++) dp[l][l + 1] = s[l] == s[l + 1] ? 0 : 1;
    for (int l = n - 3; l >= 0; l--)
    for (int r = l + 2; r <= n - 1; r++)
    dp[l][r] = s[l] == s[r] ? dp[l + 1][r - 1] : min(dp[l + 1][r], dp[l][r - 1]) + 1;
    return dp[0][n - 1];
}

2. 预测赢家

// 2. 预测赢家
// https://leetcode.cn/problems/predict-the-winner/
int maxScore(vector<int>& nums)
{
    int n = nums.size();
    vector<vector<int>> dp(n, vector<int>(n));
    for (int l = 0; l <= n - 1; l++) dp[l][l] = nums[l];
    for (int l = 0; l <= n - 2; l++) dp[l][l + 1] = max(nums[l], nums[l + 1]);
    for (int l = n - 3; l >= 0; l--)
    for (int r = l + 2; r <= n - 1; r++)
    {
        int p1 = nums[l] + min(dp[l + 2][r], dp[l + 1][r - 1]);
        int p2 = nums[r] + min(dp[l + 1][r - 1], dp[l][r - 2]);
        dp[l][r] = max(p1, p2);
    }
    return dp[0][n - 1];
}
bool predictTheWinner(vector<int>& nums) {
    int sum = accumulate(nums.begin(), nums.end(), 0);
    int first = maxScore(nums);
    int second = sum - first;
    return first >= second;
}

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

// 3. 多边形三角剖分的最低得分
// https://leetcode.cn/problems/minimum-score-triangulation-of-polygon/description/
int minScoreTriangulation(vector<int>& values) {
    int n = values.size();
    vector<vector<int>> dp(n, vector<int>(n));
    for (int l = n - 3; l >= 0; l--)
    for (int r = l + 2; r <= n - 1; r++)
    {
        dp[l][r] = INT32_MAX;
        for (int m = l + 1; m < r; m++) 
        dp[l][r] = min(dp[l][r], dp[l][m] + dp[m][r] + values[l] * values[m] * values[r]);
    }
    return dp[0][n - 1];
}

4. 切棍子的最小成本

// 4. 切棍子的最小成本
// https://leetcode.cn/problems/minimum-cost-to-cut-a-stick/
int minCost(int n, vector<int>& cuts) {
    sort(cuts.begin(), cuts.end());
    int m = cuts.size();
    vector<int> arr(m + 2);
    for (int i = 0; i < m; i++) arr[i + 1] = cuts[i];
    arr[m + 1] = n;
    // [l...r]第一次切棍子的代价为arr[r + 1] - arr[l - 1]
    vector<vector<int>> dp(m + 2, vector<int>(m + 2));
    for (int l = 1; l <= m; l++) dp[l][l] = arr[l + 1] - arr[l - 1];
    for (int l = m - 1; l >= 1; l--)
    for (int r = l + 1; r <= m; r++)
    {
        dp[l][r] = INT32_MAX;
        for (int k = l; k <= r; k++)
        dp[l][r] = min(dp[l][r], dp[l][k - 1] + dp[k + 1][r]);
        dp[l][r] += arr[r + 1] - arr[l - 1];
    }
    return dp[1][m];
}

5. 戳气球

// 5. 戳气球
// https://leetcode.cn/problems/burst-balloons/
int maxCoins(vector<int>& nums) {
    int n = nums.size();
    vector<int> arr(n + 2);
    for (int i = 0; i < n; i++) arr[i + 1] = nums[i];
    arr[0] = 1;
    arr[n + 1] = 1;
    vector<vector<int>> dp(n + 2, vector<int>(n + 2));
    for (int l = 1; l <= n; l++) dp[l][l] = arr[l - 1] * arr[l] * arr[l + 1];
    for (int l = n - 1; l >= 1; l--)
    for (int r = l + 1; r <= n; r++)
    {
        dp[l][r] = INT32_MIN;
        for (int k = l; k <= r; k++)
        dp[l][r] = max(dp[l][r], dp[l][k - 1] + dp[k + 1][r] + arr[l - 1] * arr[k] * arr[r + 1]);
    }
    return dp[1][n];
}

6. 布尔运算

// 6. 布尔运算
// https://leetcode.cn/problems/boolean-evaluation-lcci/
struct CountStruct
{
    int cntTrue = 0;
    int cntFalse = 0;
};
int countEval(string s, int result) {
    int n = s.length();
    vector<vector<CountStruct>> dp(n, vector<CountStruct>(n));
    for (int l = 0; l < n; l += 2) 
    {
        dp[l][l].cntTrue = s[l] == '0' ? 0 : 1;
        dp[l][l].cntFalse = s[l] == '0' ? 1 : 0; 
    }
    for (int l = n - 1; l >= 0; l -= 2)
    for (int r = l + 2; r <= n - 1; r += 2)
    {
        int sumTrue = 0, sumFalse = 0;
        for (int k = l + 1; k < r; k += 2)
        {
            CountStruct tmp = dp[l][k - 1];
            int lTrue = tmp.cntTrue, lFalse = tmp.cntFalse;
            tmp = dp[k + 1][r];
            int rTrue = tmp.cntTrue, rFalse = tmp.cntFalse;
            if (s[k] == '&')
            {
                sumTrue += lTrue * rTrue;
                sumFalse += lFalse * rFalse + lTrue * rFalse + lFalse * rTrue;
            }
            else if (s[k] == '|')
            {
                sumTrue += lTrue * rTrue + lTrue * rFalse + lFalse * rTrue;
                sumFalse += lFalse * rFalse;
            }
            else
            {
                sumTrue += lTrue * rFalse + lFalse * rTrue;
                sumFalse += lTrue * rTrue + lFalse * rFalse;
            }
        }
        dp[l][r].cntTrue = sumTrue;
        dp[l][r].cntFalse = sumFalse;
    }
    return result == 0 ? dp[0][n - 1].cntFalse : dp[0][n - 1].cntTrue;
}
posted @ 2025-03-15 18:49  yaoguyuan  阅读(4)  评论(0)    收藏  举报