多重背包 单调队列优化
我们注意每个dp【j】可以从dp【j-v】+ w...dp【j-k*v】+k*w转移过来,那个他们的公差是v,我们可以以对v的余数来把他们
划分成几个小组,比如背包总容量为10,这个物品的体积为3,那么我们可以把0到10划分成{0,3,6,9},{1,4,7,10},{2,5,8},
我们可以发现不同小组的是不会影响的,因为他们每个的距离都不是3的整数倍。那么对于每个小组的话,我们就可以维护dp【j-k*v】+k*w最大
,相当于我们维护一个递减的序列,然后每次要判断合不合法,就是j-c是否大于a【l】,(说明a【l】这个物品的数量不够到达 j //现在先这么理解吧,可能有错)
然后每次对首都是最大的,
#include <bits/stdc++.h> int a[1005],b[1005],dp[100005]; int w,v,c,n,V,l,r; void insert(int x,int y) { while(l<=r&&b[r]<=y)r--; a[++r]=x;b[r]=y; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&V,&n); int i,j,d; memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++) { scanf("%d%d%d",&v,&w,&c); for(d=0;d<v;d++) { l=1; r=0; for(j=0;j<=(V-d)/v;j++) { insert(j,dp[j*v+d]-j*w); if(a[l]<j-c)l++; dp[j*v+d]=b[l]+j*w; } } } printf("%d\n",dp[V]); } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步