背包问题

来源:互联网 发布:大量收购淘宝店铺 编辑:程序博客网 时间:2024/05/17 09:06

本文主要是结合以下两篇文章的理解

http://blog.csdn.net/kangroger/article/details/38864689

http://blog.csdn.net/mu399/article/details/7722810


问题:一个背包总容量为J(10),现在有I(5)个物品,第i个 物品体积为weight[i],价值为value[i],现在往背包里面装东西,怎么装能使背包的内物品价值最大?

也就是说可考虑的范围为I个物品,容量为J时背包能达到最大价值F(i,j)。那么对于第i个考虑的物品,它就存在着是否包含在这容量为J的包里的问题。(被考虑后才决定自身是否存在)

所以存在下面的转换公式

           F(i,j)=MAX{F(i-1,j),F(i-1,j-w[i])+v[i]}  ------以下图第九列为例(j=9假定固定)

(1)F(i-1,j):是指i被考虑后,最终并不存在于最后的包里,因为只需要前i-1个在包里,就能达到现在把i个考虑进去的效果,如下图中value=10,从只有考虑e,d到包括c,其价值都没变,对于此时的value,c可以不需要。


下图的说明

a:第五个物品;...... e:第一个物品,这张表是至底向上,从左到右生成的。为了叙述方便,用e2单元格表示e行2列的单元格,这个单元格的意义是用来表示只有考虑物品e时,有个承重为2的背包,那么这个背包的最大价值是0,因为e物品的重量是4,背包装不了对于d2单元格,表示只有物品e,d时,承重为2的背包,所能装入的最大价值,仍然是0,因为物品e,d都不是这个背包能装的。

nameweightvalue12345678910a26066991212151515b23033669991011c65000666661011d54000666661010e4600(e2)06666666

(2)F(i-1,j-w[i])+v[i]:是指只有当i被加到包里才能达到现在的效果,如上图10->15,a在前b,c,d,e基础上被考虑进去后,只有这第i个物品在包里,value值才能达到F(i,j)。那么在这种情况里,前i-1个物品的价值就应该扣除第i个物品所产生的效果的剩余部分:F(i-1,j-w[i])  ==》  F(5-1,9-w[5])  ==》 F(4,7)=9

以上都是在考虑范围为(i,j)时,能够达到最大F(i,j)的可能,而两者中的最大者MAX符合。


以上是j固定的假设,其实j也是变化的,如公式,要得到F(i,j)必须由表格中的其他值来相加获得,最简单的办法就是把整个表格都求出来。

这个过程其实就是填充表格从左下到右上的逐渐递推,最后到F[I][J],即上图的15处(依据转换公式逐级...)

我们的目的是i=5,j=10,先将问题小化,从0,0开始(左下)》》i增加,j增加。

代码如下:

[cpp] view plain copy
  1. #include<iostream>  
  2. using namespace std;  
  3. #define  V 1500  
  4. unsigned int f[10][V];//全局变量,自动初始化为0  
  5. unsigned int weight[10];  
  6. unsigned int value[10];  
  7. #define  max(x,y)   (x)>(y)?(x):(y)  
  8. int main()  
  9. {  
  10.       
  11.     int N,M;  
  12.     cin>>N;//物品个数  
  13.     cin>>M;//背包容量  
  14.     for (int i=1;i<=N; i++)  
  15.     {  
  16.         cin>>weight[i]>>value[i];  
  17.     }  
  18.     for (int i=1; i<=N; i++)  
  19.         for (int j=1; j<=M; j++)  
  20.         {  
  21.             if (weight[i]<=j)  
  22.             {  
  23.                 f[i][j]=max(f[i-1][j],f[i-1][j-weight[i]]+value[i]);  
  24.             }  
  25.             else  
  26.                 f[i][j]=f[i-1][j];  
  27.         }  
  28.       
  29.     cout<<f[N][M]<<endl;//输出最优解  
  30.   
  31. }  

因为这问题是先前大三下面试时遇到的(不会),现在的工作算法几乎也用不到,今天碰巧遇到,搁在心里难受,索性趁星期学习总结下,时间比较匆忙,但这是我目前对这个问题的最满意的理解,若有差错,请不吝赐教



原创粉丝点击