题目链接:https://www.luogu.org/problemnew/show/P1064
这是一个有依赖的背包问题,属于01背包的变式。这题还好,每个主件最多有2个附件,那么在对主件进行背包的时候,决策就不再是两个,而是五个。
01背包的决策:
- 不选;
- 选;
这个题目的决策:
- 不选;
- 只选主件;
- 选主件和附件1;
- 选主件和附件2;
- 选主件,附件1和附件2;
这里需要先判断选附件的决策是不是可行,即如果当前容量能放下附件1或附件2或附件1和附件2,才考虑状态转移。
因此这题的状态转移方程有4个:
f[j]=max(f[j],f[j-mv[i]]+mc[i]);
f[j]=max(f[j],f[j-mv[i]-av[i][1]]+mc[i]+ac[i][1]);
f[j]=max(f[j],f[j-mv[i]-av[i][2]]+mc[i]+ac[i][2]);
f[j]=max(f[j],f[j-mv[i]-av[i][1]-av[i][2]]+mc[i]+ac[i][1]+ac[i][2]);
其中mv表示主件的费用数组,mc表示主件的价值(费用×重要度)数组,av表示附件的费用数组,ac表示附件的价值数组。
av[i][0]表示主件i的附件个数,av[i][1/2]表示主件i的附件1/2的费用,ac[i][1/2]表示主件i的附件1/2的价值。
AC代码如下:
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 5 int n,m; 6 int mv[65],mc[65],av[65][3],ac[65][3]; 7 int f[32005]; 8 9 int main(){ 10 scanf("%d%d",&n,&m); 11 int v,p,q; 12 for(int i=1;i<=m;i++){ 13 scanf("%d%d%d",&v,&p,&q); 14 if(!q){ 15 mv[i]=v; 16 mc[i]=v*p; 17 } 18 else{ 19 av[q][0]++; 20 av[q][av[q][0]]=v; 21 ac[q][av[q][0]]=v*p; 22 } 23 } 24 for(int i=1;i<=m;i++) 25 if(mv[i]){ 26 for(int j=n;j>=mv[i];j--){ 27 f[j]=max(f[j],f[j-mv[i]]+mc[i]); 28 if(j>=mv[i]+av[i][1]) 29 f[j]=max(f[j],f[j-mv[i]-av[i][1]]+mc[i]+ac[i][1]); 30 if(j>=mv[i]+av[i][2]) 31 f[j]=max(f[j],f[j-mv[i]-av[i][2]]+mc[i]+ac[i][2]); 32 if(j>=mv[i]+av[i][1]+av[i][2]) 33 f[j]=max(f[j],f[j-mv[i]-av[i][1]-av[i][2]]+mc[i]+ac[i][1]+ac[i][2]); 34 } 35 } 36 printf("%d\n",f[n]); 37 return 0; 38 }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。