对于每一个主附件集合无非有:五种状态:
1:不选
2:主件
3:主件+附件1
4:主件+附件2
5:主件+附件1+附件2
所以对于每个主附件集合转化为至多4个物品(价值和与代价和),01背包即可
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 const int N=32010,M=65,P=10; 5 int n,m,c[M],f[N],v[M],w[M],p1[M],p2[M]; 6 int max(int x,int y){ 7 return x>y?x:y; 8 } 9 int main(){ 10 scanf("%d %d",&n,&m); 11 n/=P; 12 for (int i=1;i<=m;i++){ 13 scanf("%d %d %d",&v[i],&w[i],&c[i]); 14 v[i]/=P; 15 if (!c[i]) continue; 16 if (!p1[c[i]]) p1[c[i]]=i; 17 else p2[c[i]]=i; 18 } 19 int a,b; 20 for (int i=1;i<=m;i++){ 21 if (c[i]) continue; 22 for (int j=n;j>=0;j--){ 23 if (j-v[i]>=0)//main 24 f[j]=max(f[j],f[j-v[i]]+v[i]*w[i]); 25 if (p1[i]) 26 a=p1[i]; 27 else 28 continue; 29 if (j-v[a]-v[i]>=0)//main+1 30 f[j]=max(f[j],f[j-v[a]-v[i]]+v[i]*w[i]+v[a]*w[a]); 31 if (p2[i]) 32 b=p2[i]; 33 else 34 continue; 35 if (j-v[i]-v[b]>=0)//main+2 36 f[j]=max(f[j],f[j-v[i]-v[b]]+v[i]*w[i]+v[b]*w[b]); 37 if (j-v[i]-v[b]-v[a]>=0)//main+1+2 38 f[j]=max(f[j],f[j-v[i]-v[a]-v[b]]+v[i]*w[i]+v[a]*w[a]+v[b]*w[b]); 39 } 40 } 41 printf("%d",f[n]*P); 42 return 0; 43 }