分组背包&&有依赖的背包
这两种背包问题可以看成是完全背包(其实是多重背包),其状态转移方程 F[i][j]=max{f[i-1][j-k*v[i]]+k*w[i]} 仍然适用
对于分组背包,由于存在冲突,只能从一个组选一件,所以完全可以这样思考:
把一组看做是一个物品,选取组中的第i件看成是选取i个该物品。
这样就转换为完全背包求解了,只是将k*w[i]和k*v[i]分别映射为一个函数(对应关系)。
对于有依赖背包,可以将同一系列的物品看做一组,将不同的取法看做组中的原件,即可转化为分组背包,进而转化为完全背包。
P.S. 0/1 背包也可以看做完全背包,其中k∈[0,1];多重背包也是完全背包。所以可见,完全背包的应用和变形还是非常广的,应该灵活掌握。
附上Rqnoj P6 金明的预算方案 代码。这道题是典型的有依赖背包,也可作为有依赖背包的模板
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //rqnoj 6
2 #include <stdio.h>
3 #include <stdlib.h>
4 int m,n,e;
5 int v[100][5],c[100][5];
6 int vb[100],cb[100],fb[100];
7 int f[100][32000+1];
8 int main()
9 {
10 scanf("%d%d",&n,&m);
11 int i,j,k,a,b,max;
12 for (i=1;i<=m;i++)
13 {
14 scanf("%d%d%d",&vb[i],&cb[i],&fb[i]);
15 cb[i]*=vb[i];
16 }
17 for (i=1;i<=m;i++)
18 {
19 if (fb[i]==0)
20 {
21 a=0;b=0;
22 v[e][1]=vb[i];
23 c[e][1]=cb[i];
24 for (j=1;j<=m;j++)
25 {
26 if (fb[j]==i)
27 {if (a==0) a=j; else b=j;}
28 v[e][2]=vb[a]+vb[i];
29 c[e][2]=cb[a]+cb[i];
30 v[e][3]=vb[b]+vb[i];
31 c[e][3]=cb[b]+cb[i];
32 v[e][4]=vb[a]+vb[b]+vb[i];
33 c[e][4]=cb[a]+cb[b]+cb[i];
34 }
35 e++;
36 }
37 }
38 for (i=1;i<=m;i++)
39 for (j=1;j<=n;j++)
40 {
41 max=0;
42 for (k=0;k<5;k++)
43 if (j-v[i-1][k]>=0&&f[i-1][j-v[i-1][k]]+c[i-1][k]>max)
44 max=f[i-1][j-v[i-1][k]]+c[i-1][k];
45 f[i][j]=max;
46 }
47 printf("%d\n",f[m][n]);
48 system("pause");
49 return 0;
50 }
51
52 //5种取法(z=主件,1,2=1,2附件):0 z z+1 z+2 z+1+2
wsc500原创,转载请注明出处。请注明 出自http://www.cnblogs.com/loveidea/