分组背包

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值