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