Example:sicily 1346 “开心的金明” http://soj.me/1346
(1)大牛的思路分析:背包问题,只是主件绑定了一些附件,可以转化成分组背包,一个主件及其附件代表一组。
但是“分组背包”中一组地物品互斥,所以这里要做一次转化:将{不取,只取主件,取主件和附件1,取主件和附件2,取主件和两个附件}这个集合作为一组, 这里要庆幸最多两个附件。
解:
for (i=1;i<=m;i++) {
if (q[i]!=0) {
for (j=0;j<=n;j++)
b[j][i]=b[j][i-1];
}
else {
for (j=0;j<=n;j++) {
b[j][i]=b[j][i-1];
for (k=0;k<4;k++) {
if (j>=c[k][i]&&a[k][i]+b[j-c[k][i]][i-1]>b[j][i])
b[j][i]=a[k][i]+b[j-c[k][i]][i-1];
}
}
}
}
(2)小菜的思路:典型的分组背包,要三层循环,第三层是组内遍历,由于组内最多取一个,循环本身就保证了问题的正确性(组内不重复取);但是这个问题,我们不知道组内要取多少件,这是一个“01背包”问题,所以可以先针对“各附件集合”做一次01背包。然后再分组背包;实际上,分组时我们要解决的问题就是,对于一个容量j,组i内应该取多少个——F[i][j],找到它,再做分组背包。
解:只考虑一个组,先在组内找最优解:F[i][j],这是一个特殊的01背包:取附件的话必须取主件。注意,F并不是最终的最优解,而是各组的最优解。
所以,如何解决这个特殊的"01不背包"?