分组背包和完全背包

[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);
}
posted @ 2025-03-13 11:25  yaoguyuan  阅读(14)  评论(0)    收藏  举报