核心思路(算法):有依赖的(01)背包
说人话,就是情况多了几个:
从 ①选这个东西放包里 ②不要这个东西 变成了:
①不买主件 ②买主件 ③买主件+副件1 ④买主件+副件2 ⑤买主件+副件1+副件2
当然,前提是:
1)有附件 (没有附件是极其美好的,接下来的代码中可以看到,如果没有附件,不会产生影响)
2)该附件和主件的重量(为区分价格和价值,接下来的所有分析都按背包理解)之和≤现在在判断的j
ACcode:(详细注释,安全食用~)
#include<bits/stdc++.h>
using namespace std;
const int N=3.2e4+10;
int n,m,mw[N],mv[N],fw[N][3],fv[N][3],f[N],v,p,q;
//mw,mv:主件的体积和价值,fw,fv附件的体积和价值
void solve() {
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>v>>p>>q;
if(q==0){//主件
mw[i]=v;//体积
mv[i]=v*p;//价值
}
else{//附件
fw[q][0]++;//q主件的附件数量+1
fw[q][fw[q][0]]=v;//q主件的第fw[q][0]个附件的体积
fv[q][fw[q][0]]=v*p;//q主件的第fw[q][0]个附件的价值
}
}
//01背包模板
for(int i=1;i<=m;i++){//物品
for(int j=n;j>=mw[i];j--){//体积
//1:只要主件
f[j]=max(f[j],f[j-mw[i]]+mv[i]);
//2要主件和他的第一个附件
//(如果该主件没有附件也没影响因为是0,等于没加)
if(j>=mw[i]+fw[i][1])//如果背包容的下
f[j]=max(f[j],f[j-mw[i]-fw[i][1]]+mv[i]+fv[i][1]);
//3:要主件和第二个附件,解释如上
if(j>=mw[i]+fw[i][2])//容的下(fw[i][2]:i主件的第二附件)
f[j]=max(f[j],f[j-mw[i]-fw[i][2]]+mw[i]+fv[i][2]);
//4 主件和两个附件都要
if(j>=mw[i]+fw[i][1]+fw[i][2])
f[j]=max(f[j],f[j-mw[i]-fw[i][1]-fw[i][2]]+mv[i]+fv[i][1]+fv[i][2]);
}
}
cout<<f[n]<<"\n";//结果
}
int main() {
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
solve();
return 0;
}
over~