背包问题总结(模板)

来源:互联网 发布:网络中的信息交流 编辑:程序博客网 时间:2024/06/05 06:24

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[][]这个二维数组的巧妙。




原创粉丝点击