rt,我的做法比较奇怪。
就是把每个主件及其对应的附件丢到一个vector里,然后直接2^n状压暴力枚举出所有情况。再做一遍分组背包。
一开始我想的是如果59(n最大是60)个物品都属于同一个主件,那枚举都要2^59的计算量,妥妥T飞。结果却过掉了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define FOR_(i,a,b) for(int i=b;i>=a;i--)
const int N=70,M=3.2*1e4+10;
struct goods{int w,v;};
int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
while('0'<=c&&c<='9')x=x*10+c-'0',c=getchar();
return x*f;
}
int n,m,p[N],q[N],v[N],w[N],f[M],st[N];
vector<int> linker[N];
vector<goods> vec[N];
int main(){
m=read(),n=read();
FOR(i,1,n){
v[i]=read(),p[i]=read(),q[i]=read();
w[i]=v[i]*p[i];
if(!q[i])st[i]=1;
else linker[q[i]].push_back(i);
}
int tot=0;
FOR(i,1,n){
if(!linker[i].size()){
if(st[i])vec[++tot].push_back((goods){w[i],v[i]});
continue;
}
tot++;
int siz=linker[i].size();
FOR(sta,0,(1<<siz)-1){
int w1=0,v1=0;
FOR(j,0,siz-1)if((sta>>j)&1)
w1+=w[linker[i][j]],v1+=v[linker[i][j]];
vec[tot].push_back((goods){w1+w[i],v1+v[i]});
}
}
FOR(i,1,tot)FOR_(j,0,m)FOR(k,0,(int)vec[i].size()-1)
if(vec[i][k].v<=j)f[j]=max(f[j],f[j-vec[i][k].v]+vec[i][k].w);
printf("%d",f[m]);
return 0;
}