完全背包,0-1背包实战

完全背包

浅解:就是必须将背包装满

原题摘录

原题

简要解析

显然,这是一个完全背包问题.问题就是挑选物品,把总体积凑成40有多少种凑法?枚举显然不行.因为枚举每个物品选还是不选,有2^20种.
先可以尝试使用递归的思想.递归是很多思想的一个起点.也最容易想到.以及从他出发优化出更好的办法.
把ways(int w,int k)表示为从前k种物品凑成体积为w的凑法总数,那我们要求的不就是ways(40,n),n为输入的物品种数.

int ways(int w,int k){
	if(w==0) return 1; 
	if(k<=0) return 0;//还差一定的体积但是已经没有物品可选了 
	int a=ways(w,k-1);//没有第k种 
	int b=ways(w-a[k],k-1);//有第k种 
	return a+b;
}

进一步转化为记忆型动归,显然这里有两个变量,故用二维数组ways[w][k];

int main(){
	cin>>N;
	memset(ways,0,sizeof(ways));
	for(i=1;i<=n;i++){
		cin>>a[i];
		ways[0][i]=1;//边界条件 
	}
	ways[0][0]=1; 
	for(int w=1;w<=40;w++){
		for(int k=1;k<=N;k++){
			ways[w][k]=ways[w][k-1];
			if(w-a[k]>=0)
			ways[w][k]+=ways[w-a[k]][k-1];
		} 
	} 
	cout<<ways[40][N];
	return 0;
}

0-1背包

浅解:背包容量可以有剩余,东西要么拿,要么不拿.

原题摘录

N 个物品每个物品有价值d[i],重量w[i], 给定背包最大承重M,求背包能够装载的最大价值。每个物品只有放入背包和不放入背包两种选择。

简要解析

同上题:
我们用F[i][j]表示取前i种物品,总体积不超过j的最优取法的价值总和.
同样可以转化为记忆型动归:(取还是不取第i种)
F[i][j]=max{F[i-1][j],F[i-1][j-w[i]]+d[i]}
但是,可以发现,若总体积很大时,二维数组就要开的很大,最终导致内存不够.
注意到了这个二维数组的下一行的值,只用到了上一行的正上方及左边的值,因此可以采用滚动数组的思想,只要一行即可.所以,可以使用一维数组,递推型动归实现.

	int n, m;//物品数,背包容量
	while (cin >> n >> m)
	{
		int i, j;
		for (i = 1; i <= n; i++)
			cin >> c[i] >> v[i];
        memset(f, 0, sizeof f);
		for (i = 1; i <= n; i++)
			for(j = m; j >= c[i]; j--) 
				if (f[j] < f[j - c[i]] + v[i])
					f[j] = f[j - c[i]] + v[i];
		cout << f[m] << "\n";
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值