[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 - 1
for (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);
}