珍惜现在,感恩生活(多重背包)

悼念512汶川大地震遇难同胞——珍惜现在,感恩生活

多重背包:每个物品有多个

任意数多能用2的倍数相加表示(2进制优化)

 多重背包可转化为 0-1 背包

 多组测试样例记得重置  f 数组

memset ( f , 0 , sizeof (f) )

#include <bits/stdc++.h>
using namespace std;

const int N=20100,M=2010;
int v[N],w[N];//合并之后每个物品的体积和价值
int f[M];//存储答案 

int main(){
	 int t;
	 cin>>t;
	 while(t--){
	 	
	 	memset(f,0,sizeof(f));
	 	
		int n,m;//n个物品,背包体积为m
		cin>>m>>n;
		 
		int cnt=0;//合并之后新物品的下标 
		
		while(n--){//合并物品 
		 	
		 	int a,b,s;//每个物品的体积,价值,数量 
		 	cin>>a>>b>>s;
		 	
		 	int k=1;//k每次增长2的倍数 
		 	while(k<=s){
		 		
		 		cnt++;//先cnt++,下标从1开始
				v[cnt]=a*k;
				w[cnt]=b*k;
				
				s-=k;//合并之后物品数量减少 
				k*=2;//k倍增 
								  
			 } 
			 
			 if(s>0){//物品还有剩余 
			 	cnt++;
			 	v[cnt]=a*s;
			 	w[cnt]=b*s;
			 }
		 } //合并完成
		 
		 n=cnt;//更新合并之后的物品数量 
		 
		 for(int i=1;i<=n;i++)//0-1背包 
		 	for(int j=m;j>=v[i];j--)
		 		f[j]=max(f[j],f[j-v[i]]+w[i]);
		 		
		 cout<<f[m]<<endl;
		
	 }
	
	return 0;
} 

 多重背包模板

#include <bits/stdc++.h>
using namespace std;

const int N=20100,M=2010;
int v[N],w[N];//合并之后每个物品的体积和价值
int f[M];//存储答案 

int main(){
	 int n,m;//n个物品,背包体积为m
	 cin>>n>>m;
	 
	 int cnt=0;//合并之后新物品的下标 
	 while(n--){//合并物品 
	 	
	 	int a,b,s;//每个物品的体积,价值,数量 
	 	cin>>a>>b>>s;
	 	
	 	int k=1;//k每次增长2的倍数 
	 	while(k<=s){
	 		
	 		cnt++;//先cnt++,下标从1开始
			v[cnt]=a*k;
			w[cnt]=b*k;
			
			s-=k;//合并之后物品数量减少 
			k*=2;//k倍增 
							  
		 } 
		 
		 if(s>0){//物品还有剩余 
		 	cnt++;
		 	v[cnt]=a*s;
		 	w[cnt]=b*s;
		 }
	 } //合并完成
	 
	 n=cnt;//更新合并之后的物品数量 
	 
	 for(int i=1;i<=n;i++)//0-1背包 
	 	for(int j=m;j>=v[i];j--)
	 		f[j]=max(f[j],f[j-v[i]]+w[i]);
	 		
	 cout<<f[m]<<endl;
	
	return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值