1.朴素多重背包
先枚举每一个物品,再枚举物品个数,最后枚举现在的重量时间复杂度
for(int i=1;i<=n;i++){
for(int j=1;j<=n[i];j++){
for(int k=w;k>=j*w[i];k--){
dp[k]=max(dp[k],dp[k-j*v[i]]+j*w[i])
}
}
}
2.单调队列优化多重背包
每一个物品更新的时候,更新到体积为n的状态,都是与n于w[i]的模数相等的状态转移而来的,所所以对于每个物品i,都有
也就是:
可以将符合条件的dp[n*v[i]+j]-n*w[i]用单调队列维护,每个数都只会进出队列一次,就可以将一维复杂度,为
for(int j=0;j<v[i];j++){
deque<pair<int,int> >q;
int gs=(t-j)/v[i];
for(int k=gs;k>=max(0,gs-n[i]);k--){
while(!q.empty()&&q.back().first<=dp[k*v[i]+j]-k*w[i]) q.pop_back();
q.push_back(make_pair(dp[k*v[i]+j]-k*w[i],k));
}//先将所有符合条件的都存入队列
int o=gs-n[i];
for(int k=gs;k>0;k--){
while(q.front().second>=k) q.pop_front();//不符合条件的弹出
dp[k*v[i]+j]=max(dp[k*v[i]+j],q.front().first+k*w[i]);
o--;
if(o<0) continue;
while(!q.empty()&&q.back().first<=dp[o*v[i]+j]-o*w[i]) q.pop_back();//没有这个优的弹出
q.push_back(make_pair(dp[o*v[i]+j]-o*w[i],o));
}
}