旅行商的背包
题目描述
小 S 坚信任何问题都可以在多项式时间内解决,于是他准备亲自去当一回旅行商。在出发之前,他购进了一些物品。这些物品共有 n n n 种,第 i i i 种体积为 V i V_i Vi,价值为 W i W_i Wi,共有 D i D_i Di 件。他的背包体积是 C C C。怎样装才能获得尽量多的收益呢?作为一名大神犇,他轻而易举的解决了这个问题。
然而,就在他出发前,他又收到了一批奇货。这些货共有 m m m 件,第 i i i 件的价值 Y i Y_i Yi 与分配的体积 X i X_i Xi 之间的关系为: Y i = a i X i 2 + b i X i + c i Y_i=a_iX_i^2+b_iX_i+c_i Yi=aiXi2+biXi+ci。这是件好事,但小 S 却不知道怎么处理了,于是他找到了一位超级神犇(也就是你),请你帮他解决这个问题。
输入格式
第一行三个数 n , m , C n,m,C n,m,C,如题中所述;
以下 n n n 行,每行有三个数 V i , W i , D i V_i,W_i,D_i Vi,Wi,Di,如题中所述;
以下 m m m 行,每行有三个数 a i , b i , c i a_i,b_i,c_i ai,bi,ci,如题中所述。
输出格式
仅一行,为最大的价值。
样例 #1
样例输入 #1
2 1 10
1 2 3
3 4 1
-1 8 -16
样例输出 #1
10
提示
样例解释
前两种物品全部选走,最后一个奇货分给 4 4 4 的体积,收益为 2 × 3 + 4 × 1 + ( − 1 ) × 16 + 8 × 4 + ( − 16 ) = 10 2 \times 3+4 \times 1+(-1) \times 16+8 \times 4+(-16)=10 2×3+4×1+(−1)×16+8×4+(−16)=10。
限制与约定
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 1 0 4 1 \le n \le 10^4 1≤n≤104, 1 ≤ m ≤ 5 1 \le m \le 5 1≤m≤5, 1 ≤ C ≤ 1 0 4 1 \le C \le 10^4 1≤C≤104, 1 ≤ W i , V i , D i ≤ 1000 1 \le W_i,V_i,D_i \le 1000 1≤Wi,Vi,Di≤1000, − 1000 ≤ a i , b i , c i ≤ 1000 -1000 \le a_i,b_i,c_i \le 1000 −1000≤ai,bi,ci≤1000。
思路
这道题一看背包容量固定,物品数量有限,那就是多重背包了。
- 但你别被最后的那个吓到,因为它是吃剩下的。
- 因而我们可以先对上面的进行多重背包完了之后对后面的进行多重背包。
因为你这里m很小,我们对下面的多重背包可以不用二进制优化。
代码
//多重背包问题
#include<iostream>
#define int long long
using namespace std;
const int N = 1e4+10;
int n,m,V;
int v[N],w[N],s[N];
int a[N],b[N],c[N];
int f[N];
signed main(){
cin>>n>>m>>V;
for(int i=1;i<=n;i++){
cin>>v[i]>>w[i]>>s[i];
for(int k=1;k<=s[i];k<<=1){
for(int j=V;j>=k*v[i];j--){
f[j]=max(f[j],f[j-k*v[i]]+k*w[i]);
}
s[i]-=k;
}
if(s[i]){
for(int j=V;j>=s[i]*v[i];j--){
f[j]=max(f[j],f[j-v[i]*s[i]]+s[i]*w[i]);
}
}
}
for(int i=1;i<=m;i++){
cin>>a[i]>>b[i]>>c[i];
}
//这个也就是多重背包朴素版
for(int i=1;i<=m;i++){
for(int j=V;j>=0;j--){//可以装和不装(所以要枚举到0)
for(int k=0;k<=j;k++){//枚举每个数量的
f[j]=max(f[j],f[j-k]+a[i]*k*k+b[i]*k+c[i]);
}
}
}
cout<<f[V];
return 0;
}