题意:有(n)种物品,第(i)种体积为(V_i),价值为(W_i),共有(D_i)件.的背包体积是(C).还有m件奇货,第(i)件的价值(Y_i)与分配的体积(X_i)之间的关系为(Y_i=a_i*X_i^2+b_i*X_i+c_i).求最大价值.(1≤n,C≤10000,1≤m≤5,1≤Wi,Vi,Di≤1000,-1000≤ai,bi,ci≤1000.)
分析:前面n种物品是多重背包来做,二进制优化或者单调队列优化都可以.后面m件物品是完全背包,直接枚举分配的体积就好了.
无力吐槽这道题.自己的单调队列优化多重背包怎么都T两个点,别人的跑得飞快.
把自己的辣鸡80分代码也挂出来吧,希望引以为戒.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define rg register
using namespace std;
inline int read(){
rg int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int N=10005;
int q[N],f[2][N];
inline int maxx(int a,int b){if(a>b)return a;return b;}
int main(){
rg int n=read(),m=read(),C=read();
for(rg int i=1;i<=n;++i){
rg int v=read(),w=read(),d=read();
for(rg int j=0;j<v;++j){
rg int l=1,r=0;
for(rg int k=j;k<=C;k+=v){
while(l<=r&&k-q[l]>v*d)++l;
while(l<=r&&f[(i-1)&1][q[r]]-q[r]/v*w<f[(i-1)&1][k]-k/v*w)--r;
q[++r]=k;
f[i&1][k]=f[(i-1)&1][q[l]]+(k-q[l])/v*w;
}
}
}
for(rg int i=1;i<=m;++i){
rg int a=read(),b=read(),c=read();
for(rg int j=C;j>=0;--j)
for(rg int k=0;k<=j;++k)
f[n&1][j]=maxx(f[n&1][j],f[n&1][j-k]+a*k*k+b*k+c);
}
printf("%d
",f[n&1][C]);
return 0;
}
题解代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define rg register
using namespace std;
inline int read(){
rg int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int N=1e4+5;
int dp[N],f[N],q[N];
int main(){
rg int n=read(),m=read(),C=read();
for(rg int i=1;i<=n;++i){
rg int v=read(),w=read(),d=read();
for(rg int j=0;j<v;++j){
rg int l=1,r=0;
for(rg int k=0;k*v+j<=C;++k){
rg int x=dp[k*v+j]-k*w;
while(l<=r&&x>f[r])--r;
q[++r]=k;f[r]=x;
if(q[l]+d<k)++l;
dp[k*v+j]=f[l]+k*w;
}
}
}
for(rg int i=1;i<=m;++i){
rg int a=read(),b=read(),c=read();
for(rg int j=C;j>=0;--j)
for(rg int k=0;k<=j;++k)
if(dp[j-k]+(a*k+b)*k+c>dp[j])dp[j]=dp[j-k]+(a*k+b)*k+c;
}
printf("%d
",dp[C]);
return 0;
}