变形的多重背包,用二进制先把多重背包转化成01背包,然后再根据每次查询,跳过需要去掉的玩偶,然后开始愉快的dp,然后发现超时了.所以我们得换思路,用空间换时间,用前后缀数组来计算每次的查询,这样时间复杂度就降低了.
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
int main(){
int n;
cin>>n;
vector<vector<pii>>groups(n);
//进行二进制处理
for(int i=0;i<n;i++){
int a,b,c;
cin>>a>>b>>c;
int t=1;
while(c){
int g=min(c,t);
c-=g;
t*=2;
groups[i].push_back({a*g,b*g});
}
}
/*定义前后缀数组,可以先储存查询的值,用最大e值定义数组,这样可以减少时间,但我比
较懒,就直接用最大值定义了 */
vector<vector<int>>pre(n+1,vector<int>(1005));
vector<vector<int>>suf(n+1,vector<int>(1005));
//前缀数组递推
for(int i=1;i<=n;i++){
pre[i]=pre[i-1];
for(auto[w,v]:groups[i-1]){
for(int j=1003;j>=w;j--){
pre[i][j]=max(pre[i][j],pre[i][j-w]+v);
}
}
}
//后缀数组递推
for(int i=n-1;i>=0;i--){
suf[i]=suf[i+1];
for(auto[w,v]:groups[i]){
for(int j=1003;j>=w;j--){
suf[i][j]=max(suf[i][j],suf[i][j-w]+v);
}
}
}
int q;
cin>>q;
while(q--){
int d,e;
cin>>d>>e;
int ans=0;
for(int k=0;k<=e;k++){
ans=max(ans,pre[d][k]+suf[d+1][e-k]);
}
cout<<ans<<endl;
}
}

京公网安备 11010502036488号