int V;//容量
//01
void zeroone(int cost,int val){//费用,价值
int i;
for(i=V;i>=cost;i--){
if(dp[i]<dp[i-cost]+val){
dp[i] = dp[i-cost]+val;
}
}
}
//完全背包
void complete(int cost,int val){//费用,价值
int i;
for(i=cost;i<=V;i++){
if(dp[i]<dp[i-cost]+val){
dp[i] = dp[i-cost]+val;
}
}
}
//多重背包
void multi(int cost,int val,int cnt){//费用,价值,数量
if(cost*cnt>=V){
complete(cost,val);
return ;
}
int k = 1;
while(k<cnt){
zeroone(k*cost,k*val);
cnt -= k;
k *= 2;
}
zeroone(cnt*cost,cnt*val);
}
//混合三种背包:
for(i=0;i<m;i++){
scanf("%d%d%d%d",&v,&weight,&value,&n);
if(v>V || weight>W)
continue;
if(n==1)
zeroone(v,weight,value);
else if(n==0)
complete(v,weight,value);
else
multiply(v,weight,value,n);
}
//二维费用的背包:
void zeroone(int v,int weight,int value){
int i,j;
for(i=V;i>=v;i--)
for(j=W;j>=weight;j--)
if(dp[i][j]<dp[i-v][j-weight]+value)
dp[i][j]=dp[i-v][j-weight]+value;
}
void complete(int v,int weight,int value){
int i,j;
for(i=v;i<=V;i++)
for(j=weight;j<=W;j++)
if(dp[i][j]<dp[i-v][j-weight]+value)
dp[i][j]=dp[i-v][j-weight]+value;
}
void multiply(int v,int weight,int value,int count){
if(v*count>=V || weight*count>=W){
complete(v,weight,value);
return;
}
int k=1;
while(k<count){
zeroone(k*v,k*weight,k*value);
count-=k;
k*=2;
}
zeroone(count*v,count*weight,count*value);
}
//分组背包:
for(i=1;i<=n;i++){ //枚举组
for(j=m;j>=1;j--){ //背包容量
for(k=1;k<=m;k++){ //不同费用的物品
if(j>=k) //转移方程有j-k,要保证j-k>=0
dp[j] = max(dp[j],dp[j-k]+a[i][k]);
}
}
}