多重背包

[Algo] 多重背包

1. 多重背包 - 二进制分组优化

// 1. 多重背包 - 二进制分组优化
// https://www.luogu.com.cn/problem/P1776
int func(int n, int t, vector<int> &w, vector<int> &v)
{
    vector<int> dp(t + 1);
    for (int i = 1; i <= n; i++)
    for (int j = t; j >= w[i - 1]; j--)
    dp[j] = max(dp[j], dp[j - w[i - 1]] + v[i - 1]);
    return dp[t];
}
int maxValue(int n, int t, vector<int> &w, vector<int> &v, vector<int> &c)
{
    int new_n = 0;
    vector<int> new_w, new_v;
    for (int i = 0; i < n; i++)
    {
        int rest = c[i];
        for (int k = 1; k <= rest; k <<= 1)
        {
            new_w.push_back(k * w[i]);
            new_v.push_back(k * v[i]);
            new_n++;
            rest -= k;
        }
        if (rest != 0)
        {
            new_w.push_back(rest * w[i]);
            new_v.push_back(rest * v[i]);
            new_n++;
        }
    }
    return func(new_n, t, new_w, new_v);
}

2. 多重背包 - *单调队列优化(索引从1开始)

// 2. 多重背包 - *单调队列优化(索引从1开始)
// https://www.luogu.com.cn/problem/P1776
int value(vector<vector<int>> &dp, vector<int> &w, vector<int> &v, int i, int j)
{
    return dp[i - 1][j] - j / w[i] * v[i];
}
int maxValue_(int n, int t, vector<int> &w, vector<int> &v, vector<int> &c)
{
    vector<vector<int>> dp(n + 1, vector<int>(t + 1));
    for (int i = 1; i <= n; i++)
    for (int mod = 0; mod <= min(t, w[i] - 1); mod++)
    {
        deque<int> dq;
        for (int j = mod; j <= t; j += w[i])
        {
            while (!dq.empty() && value(dp, w, v, i, dq.back()) <= value(dp, w, v, i, j)) dq.pop_back();
            dq.push_back(j);
            if (dq.front() == j - w[i] * (c[i] + 1)) dq.pop_front();
            dp[i][j] = value(dp, w, v, i, dq.front()) + j / w[i] * v[i];
        }
    }
    return dp[n][t];
}
posted @ 2025-03-14 15:00  yaoguyuan  阅读(15)  评论(0)    收藏  举报