Leetcode算法题总结之区间dp

Leetcode算法题总结之区间dp

1. 312 戳气球

https://leetcode-cn.com/problems/burst-balloons/

class Solution {
public:
    int maxCoins(vector<int>& nums) {
        nums.insert(nums.begin(), 1);
        nums.push_back(1);
        int size = nums.size();
        vector<vector<int>> dp(size, vector<int>(size, 0));
        dp[0][0] = 1;
        for(int i = size - 2; i >= 0; i--){
            for(int j = i + 2; j < size; j ++){
                for(int k = i + 1; k < j; k ++){
                    dp[i][j] = max(dp[i][j], dp[i][k] + dp[k][j] + nums[i] * nums[j] * nums[k] );
                }
            }
        }
        return dp[0][size-1];
    }
};

2. 1547 切棍子的最小成本

https://leetcode-cn.com/problems/minimum-cost-to-cut-a-stick/

class Solution {
public:
    int minCost(int n, vector<int>& cuts) {
        cuts.push_back(0);
        cuts.push_back(n);
        sort(cuts.begin(), cuts.end());
        int size = cuts.size();
        vector<vector<int>> dp(size, vector<int>(size, 0x3f3f3f3f));
        dp[0][0] = 0;
        for(int i = 1; i < size; i++){
            dp[i][i] = 0; dp[i-1][i] = 0;
        }
        for(int i = size - 2; i >= 0; i--){
            for(int j = i + 2; j < size; j++){
                for(int k = i + 1; k < j; k++){
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j] + cuts[j]-cuts[i]);
                }
            }
        }
        return dp[0][size-1];
    }
};

3. 1000 合并石头的最低成本

https://leetcode-cn.com/problems/minimum-cost-to-merge-stones/

class Solution {
public:
    int mergeStones(vector<int>& stones, int K) {
        int size = stones.size();
        if(size == 1) return 0;
        if((size - 1) % (K - 1)) return -1;
        vector<int> sums(size+1, 0);
        vector<vector<int>> dp(size, vector<int>(size, 0));
        sums[1] = stones[0];
        for(int i = 2; i <= size; i++)
            sums[i] = sums[i-1] + stones[i-1];
        for(int i = size - K + 1; i >= 0; i--){
            for(int j = i + K - 1; j < size; j++){
                dp[i][j] = 0x3f3f3f3f;
                for(int k = i; k < j; k += (K-1))
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j]);
                if((j - i) % (K - 1) == 0) dp[i][j] += sums[j+1] - sums[i];
            }
        }
        return dp[0][size - 1];
    }
};

4. 813 最大平均值和的分组

https://leetcode-cn.com/problems/largest-sum-of-averages/

class Solution {
public:
    double largestSumOfAverages(vector<int>& A, int K) {
        int size = A.size();
        vector<vector<double>> dp(size+1, vector<double>(K+1, 0));
        vector<int> sums(size + 1, 0);
        for(int i = 1; i <= size; i ++){
            sums[i] = sums[i-1] + A[i-1];
            dp[i][1] = sums[i] * 1.0 / i;
        }
        for(int k = 2; k <= K; k ++){
            for(int i = k; i <= size; i ++){
                for(int j = k-1; j < i; j++){
                    dp[i][k] = max(dp[i][k], dp[j][k-1] + (sums[i] - sums[j]) * 1.0 / (i - j));
                }
            }
        }
        return dp[size][K];
    }
};

5. 647 回文子串

https://leetcode-cn.com/problems/palindromic-substrings/

class Solution {
public:
    bool dp[1000][1000];
    int countSubstrings(string s) {
        int size = s.size();
        dp[0][0] = true;
        for(int i = 1; i < size; i++){
            dp[i][i] = true;
            if(s[i-1] == s[i]){
                dp[i-1][i] = true;
            }
        }
        for(int len = 2; len < size; len ++){
            for(int i = 0; i < size - len; i++){
                int j = i + len;
                dp[i][j] = dp[i+1][j-1] && s[i] == s[j];
            }
        }
        int sum = 0; //用 accumulate 函数计算总和
        for(const auto & v : dp)
            sum = accumulate(v, v + size, sum);
        return sum;
    }
};

6. 730 统计不同回文子序列

https://leetcode-cn.com/problems/count-different-palindromic-subsequences/

class Solution {
public:
    int dp[1000][1000];
    int countPalindromicSubsequences(string S) {
        int size = S.size();
        dp[0][0] = 1;
        for(int i = 1; i < size; i++){
            dp[i][i] = 1;
            dp[i-1][i] = 2;
        }
        for(int len = 2; len < size; len++){
            for(int i = 0; i < size - len; i ++){
                int j = i + len;
                if(S[i] != S[j]) 
                    dp[i][j] = dp[i+1][j] + dp[i][j-1] - dp[i+1][j-1];
                else{
                    dp[i][j] = 2 * dp[i+1][j-1];
                    int left = i + 1, right = j - 1;
                    while(left <= right && S[left] != S[i]) left ++;
                    while(left <= right && S[right] != S[i]) right --;
                    if(left == right) dp[i][j] += 1;
                    else if(left > right) dp[i][j] += 2;
                    else
                        dp[i][j] -= dp[left+1][right-1];
                }
                dp[i][j] = dp[i][j] < 0 ? dp[i][j] + 1000000007 : dp[i][j] % 1000000007;
            }
        }
        return dp[0][size-1];
    }
};

7. 87 扰乱字符串

https://leetcode-cn.com/problems/scramble-string/submissions/

class Solution {
public:
    bool dp[100][100][101];
    bool isScramble(string s1, string s2) {
        int size = s1.size();
        // vector<vector<vector<bool>>> dp(size, vector<vector<bool>>(size, vector<bool>(size+1, false)));
        for(int i = 0; i < size; i++)
            for(int j = 0; j < size; j++)
                dp[i][j][1] = (s1[i] == s2[j]);
        for(int len = 2; len <= size; len++){
            for(int i = 0; i <= size - len; i++){
                for(int j = 0; j <= size-len; j++){
                    for(int k = 1; !dp[i][j][len] && k < len; k ++){
                        dp[i][j][len] = (dp[i][j][k] && dp[i+k][j+k][len-k]) || (dp[i][j+len-k][k] && dp[i+k][j][len-k]);
                        // if(dp[i][j][len]) break;
                    }
                }
            }
        }
        return dp[0][0][size];
    }
};

8. 5 最长回文串

https://leetcode-cn.com/problems/longest-palindromic-substring/

class Solution {
public:
    bool dp[1001][1001];
    string longestPalindrome(string s) {
        int size = s.size();
        string res = s.substr(0,1);
        dp[0][0] = true;
        // for(int i = 1; i < size; i++){
        //     dp[i][i] = true;
        //     dp[i-1][i] = (s[i-1] == s[i]);
        //     if(dp[i-1][i]) res = s.substr(i-1, 2);
        // }
        for(int len = 0; len < s.size(); len++){
            for(int start = 0; start < s.size() - len; start ++){
                int end = start + len;
                if(len == 0) dp[start][end] = 1;
                else if(len == 1) dp[start][end] = (s[start] == s[end]);
                else dp[start][end] = (dp[start+1][end-1] && (s[start] == s[end]));
                if(dp[start][end] && len + 1 > res.size())
                    res = s.substr(start, len + 1);
            }
        }
        return res;
    }
};

9. 516 最长回文子序列

https://leetcode-cn.com/problems/longest-palindromic-subsequence/

class Solution {
public:
    int dp[1000][1000];
    int longestPalindromeSubseq(string s) {
        int size = s.size();
        for(int i = size - 1; i >= 0; i--){
            dp[i][i] = 1;
            for(int j = i + 1; j < size; j++){
                if(s[i] == s[j]) dp[i][j] = dp[i+1][j-1] + 2;
                else dp[i][j] = max(dp[i+1][j], dp[i][j-1]);
            }
        }
        return dp[0][size-1];
    }
};

10. 1246 删除回文子数组

https://leetcode-cn.com/problems/palindrome-removal/

class Solution {
public:
    int dp[100][100];
    int minimumMoves(vector<int>& arr) {
        memset(dp, 0x3f3f3f3f, sizeof(dp));
        int size = arr.size();
        dp[0][0] = 1;
        for(int i = 1; i < size; i++){
            dp[i][i] = 1;
            dp[i-1][i] = (arr[i-1] == arr[i] ? 1 : 2);
        }
        
        // for(int len = 2; len < size; len++){
        //     for(int i = 0; i < size - len; i++){
        //         int j = i + len;
        //         for(int k = i; k < j; k++){
        //             dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j]);
        //         }
        //         if(arr[i] == arr[j]) dp[i][j] = min(dp[i][j], dp[i+1][j-1]);
        //     }
        // }

        for(int i = size - 2; i >= 0; i--){
            for(int j = i + 1; j < size; j++){
                for(int k = i; k < j; k++)
                    dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j]);
                if(arr[i] == arr[j]) dp[i][j] = min(dp[i][j], dp[i+1][j-1]);
            }
        }
        return dp[0][size-1];
    }
};
posted @ 2020-08-14 22:38  hou永胜  阅读(1200)  评论(0编辑  收藏  举报