背包问题总结(模板)

01背包:

  有n个物品,每个物品对应的价值和体积,且每个物品只能选一次,背包体积为V求背包所能装物品的最大价值

#include<iostream>
#include<cstdio>
const int maxn=10002;//n表示物品个数 
int f[maxn],v[maxn],val[maxn],V,n;//V表示背包体积 
using namespace std;//v[]表示物品的体积, 
int main()//val[]表示物品的价值 
{
	scanf("%d%d",&n,&V);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&v[i],&val[i]);
	}
	for(int i=1;i<=n;i++)
	   for(int j=V;j>=v[i];j--)
	      f[j]=max(f[j],f[j-v[i]]+val[i]);
	printf("%d",f[V]); 
	return 0;
}
完全背包:

和01背包基本类似,不同的只是每种物品可以取无数次;

对于完全背包的一维递推方程,我们只需要更改一下循环方向即可

for(int i=1;i<=n;i++)
	   for(int j=v[i];j<=V;j++)
	      f[j]=max(f[j],f[j-v[i]]+val[i]);//完全背包代码核心;
多重背包:

对于每一件物品我们对其规定件数(最多能使用多少件),我们可以对于每一种物品,枚举其件数,对于每一件物品,我们对其的状态只有两种:拿,不拿;所以我们可以转化成为01背包来求解

//第一层我们枚举物品种类
//第二层我们枚举背包体积;
//第三层我们枚举每种物品的个数 
for(int i=1;i<=n;i++)
	for(int j=V;j>=0;j--)
	   for(int k=0;k<=c[i];k++)
	      if(k*v[i]>j) break;//注意特判 
	      else f[j]=max(f[j],f[j-k*v[i]]+k*val[i]);
printf("%d",f[V]);
	  
分组背包:

我们来看一下什么是分组背包?

有N件物品和一个容量为V的背包,对于每一件物品给出该物品的体积价值和组别,由于每组的物品之间相互冲突,所以对于每组物品我们最多选择一件,求解将哪些物品装入背包可使体积总和不超过背包容量且价值最大;

也就是说我们可以从分组的角度来看,这其实是一个01背包问题,选或不选一个组的某一个物品:

对于分组背包我向大家推荐一种存储方式,这种方式让代码简洁易懂

我们在存储组数的时候可以开一个二维数组a[][],用a[i][0]来表示组别为i的物品的个数;

然后用a[i][j]来表示组别为i的第几的物品,

附上伪代码:

 for k=所有的组数

   for v=V...0;

       for 所有的i属于k组的

      f[v]=max(f[v],f[v-v[a[k][i]]]+val[a[k][i]]])

大家可以好好体会一下a[][]这个二维数组的巧妙。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值