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];
}
};