1.每组物品只能选一件,求最大价值。
例题:洛谷P1757 通天之分组背包
int w[10001],t,c[10001],v,f[10001],a[10001][1001],m,n,p;
int main() {
scanf("%d%d",&m,&n);
for(int i=1; i<=n; i++) {
scanf("%d%d%d",&w[i],&c[i],&p);
a[p][++a[p][0]]=i;
t=max(t,p);
}
for(int k=1; k<=t; k++)//控制组数
for(int j=m; j>=0; j--)//容量
for(int i=1; i<=a[k][0]; i++)//枚举
if(w[a[k][i]]<=j)//先判断能不能放
f[j]=max(f[j],f[j-w[a[k][i]]]+c[a[k][i]]);
printf("%d",f[m]);
}
2.每组物品只能选一件,每组都要选。求最少的前k种方案
例题:洛谷P2409 Y的积木
int f[101][100001],a[1001][1001],m,n,p,s=0;
int main() {
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) {
scanf("%d",&a[i][0]);
int maxa=0;
for(int j=1;j<=a[i][0];j++){
scanf("%d",&a[i][j]);
maxa=max(maxa,a[i][j]);
}
s+=maxa;
}
f[0][0]=1;
for(int k=1; k<=n; k++)//控制组数
for(int j=s; j>=0; j--)//容量
for(int i=1; i<=a[k][0]; i++)//枚举
if(a[k][i]<=j)//先判断能不能放
f[k][j]+=f[k-1][j-a[k][i]];
int j=0;
for(int i=1;i<=s&&j<m;i++){
while(f[n][i]&&j<m){
cout<<i<<" ";j++,f[n][i]--;
}
}
}
3.每组物品最少选一件,求最大价值
例题hdu3033I love sneakers! http://acm.hdu.edu.cn/showproblem.php?pid=3033
//http://www.cnblogs.com/KonjakJuruo/p/5971968.html
const int N=11000,S=110;
int n,m,K,a[N],b[N],c[N],mn[S],d[S][S],f[S][N];
int main() {
while(scanf("%d%d%d",&n,&m,&K)!=EOF) {
memset(mn,63,sizeof(mn));
for(int i=1; i<=n; i++) {
scanf("%d%d%d",&a[i],&b[i],&c[i]);
d[a[i]][++d[a[i]][0]]=i;
mn[a[i]]=min(mn[a[i]],b[i]);
}
int x=0;
for(int i=1; i<=K; i++) x+=mn[i];
if(m<x) printf("Impossible\n");
else {
for(int k=1; k<=K; k++) {//组数
for(int i=1; i<=d[k][0]; i++) {//每组的物品
x=d[k][i];
for(int j=m; j>=b[x]; j--) {//体积
f[k][j]=max(f[k][j],max(f[k-1][j-b[x]]+c[x],f[k][j-b[x]]+c[x]));
}
}
}
printf("%d\n",f[K][m]);
}
}
return 0;
}