多重背包的最最最朴素写法
vector<int> dp1(weight + 1,0);
for (int i = 0;i < n;i++){
for (int j = weight;j >= 0;j--){
for (int k = 0;k <= m[i] && (j - w[i] * k) >= 0;k++){
dp1[j] = max(dp1[j],dp1[j - k * w[i]] + k * val[i]);
}
}
}
但是,很明显这并不是最优的方法,我们可以利用倍增的思想对这个问题进行二进制分组优化
vector<pair<int,int>> v; //first:weight second:val
for (int i = 0;i < n;i++){
int turns = m[i];
for (int j = 1;j <= turns;j <<= 1){
v.push_back(make_pair(j * w[i],val[i] * j));
turns -= j;
}
if (turns > 0){
v.push_back(make_pair(turns * w[i],turns * val[i]));
}
}
vector<int> dp(weight + 1,0);
for (int i = 0;i < v.size();i++){
for (int j = weight;j >= v[i].first;j--){
dp[j] = max(dp[j],dp[j - v[i].first] + v[i].second);
}
}
在大多数情况下,二进制分组已经可以通过了,但是如果条件严苛的话,还需要进行单调队列优化
deque<pair<int,int>> d; //first:index second:dp2
vector<int> dp2(weight + 1,0);
for (int i = 0;i < n;i++){
for (int mod = 0;mod <= w[i] - 1;mod++){
d.clear();
for (int j = mod;j <= weight;j += w[i]){
while(!d.empty() && d.back().second + (j - d.back().first) / w[i] * val[i] <= dp2[j]){
d.pop_back();
}
while (!d.empty() && (j - d.front().first) / w[i] > m[i]){
d.pop_front();
}
d.push_back(make_pair(j,dp2[j]));
dp2[j] = max(dp2[j],d.front().second + (j - d.front().first) / w[i] * val[i]);
}
}
}