[Algo] 分组背包和完全背包
1. 分组背包模板
// 1. 分组背包模板
// https://www.luogu.com.cn/problem/P1757
int maxValue(vector<vector<int>> &arr, int n, int m)
{// arr[i][0] - 重量, arr[i][1] - 价值, arr[i][2] - 组号// 先按照组号排序sort(arr.begin(), arr.end(), [](const vector<int> &a, const vector<int> &b) { return a[2] < b[2]; });int k = arr[n - 1][2];vector<vector<int>> dp(k + 1, vector<int>(m + 1));// dp[i][j]: 1...i组每组至多选一个物品且容量不超过j时能够获得的最大价值for (int i = 1, start = 0, end = 1; i <= k; i++){// 当前来到第i组while (end < n && arr[end][2] == arr[start][2]) end++;// 第i组所有物品下标范围start...end - 1for (int j = 0; j <= m; j++){dp[i][j] = dp[i - 1][j];for (int k = start; k < end; k++)if (j >= arr[k][0]) dp[i][j] = max(dp[i][j], dp[i - 1][j - arr[k][0]] + arr[k][1]);}start = end++;}return dp[k][m];
}
2. 从栈中取出K个硬币的最大面值和
// 2. 从栈中取出K个硬币的最大面值和
// https://leetcode.cn/problems/maximum-value-of-k-coins-from-piles/
int maxValueOfCoins(vector<vector<int>>& piles, int k) {vector<vector<int>> arr;int n = piles.size(), count = 0;for (int i = 0; i < n; i++){int group = i + 1, m = piles[i].size(), sum = 0;for (int j = 0; j < m; j++){sum += piles[i][j];vector<int> tmp(3);tmp[0] = j + 1;tmp[1] = sum;tmp[2] = group;arr.push_back(tmp);count++;}}return maxValue(arr, count, k);
}
3. 完全背包模板
// 3. 完全背包模板
// https://www.luogu.com.cn/problem/P1616
int maxValue_(vector<int> &w, vector<int> &v, int m)
{int n = w.size();vector<int> dp(m + 1);for (int i = 1; i <= n; i++)for (int j = w[i]; j <= m; j++) dp[j] = max(dp[j], dp[j - w[i]] + v[i]);return dp[m];
}
4. 正则表达式匹配
// 4. 正则表达式匹配
// https://leetcode.cn/problems/regular-expression-matching/description/
bool regexMatch(string &s, string &p, int i, int j, vector<vector<int>> &dp)
{if (dp[i][j] != 0) return dp[i][j] == 1;bool ans;int n = s.size(), m = p.size();// s已越界if (i == n){// (1)p也越界if (j == m) ans = true;// (2)p未越界else ans = j + 1 < m && p[j + 1] == '*' && regexMatch(s, p, i, j + 2, dp);}// s未越界,p已越界else if (j == m){ans = false;}// s与p都未越界else{// (1)p[j + 1]越界或非'*'if (j + 1 == m || p[j + 1] != '*') ans = (s[i] == p[j] || p[j] == '.') && regexMatch(s, p, i + 1, j + 1, dp);// (2)p[j + 1] == '*'else {bool p1 = regexMatch(s, p, i, j + 2, dp);bool p2 = (s[i] == p[j] || p[j] == '.') && regexMatch(s, p, i + 1, j, dp);ans = p1 | p2;}}dp[i][j] = ans == true ? 1 : 2;return ans;
}
bool isMatch(string s, string p) {vector<vector<int>> dp(s.size() + 1, vector<int>(p.size() + 1));return regexMatch(s, p, 0, 0, dp);
}