对于每一个主附件集合无非有:五种状态:

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 }
STD

 

posted on 2016-10-29 18:37  Absolutezero  阅读(203)  评论(0编辑  收藏  举报