0-1背包问题

   转自:http://www.cppblog.com/jince/archive/2010/09/11/126409.aspx?opt=admin

在别人眼里轻而易举的的事情落在自己身上可能比登天还要难!!
                0-1背包问题:给定n中物品和一个背包。物品i的重量是wi,价值为vi,背包的容量为c。问如何选择装入背包中的武平,使得装入背包中的物品价值最大?
               书上有一行行的算式,证明最优子结构性质和构造递归关系。我没怎么看明白最优子结构,但是我能看懂递归关系式!!我记得当时老师叫我们的时候我自己想了好几天才想明白这个递归式,但是始终觉得有点虚,借此我再写一下!
               设数组m(i,j)代表背包容量为j,可选物品为i,i+1,..n时的最优解(这里的最优解指的是选择方案,并非正真的最优值),显然m(1,c)是0-1背包问题的解(这里是书上的错误,应该是m[1]中的最大值!!我后来才发现的。。)。这种定义虽然比较拗口,但是还是可以接受的,其实我们也可以这么定义m[i][j],代表背包容量为j,当前选择物品为a[i]时的最优解,显然m数组中第n行的最大值是0-1背包问题的解!!

第一种定义的递归式如下:
                                               
1
   m[i][j]=max{m[i+1][j],m[i+1][j-wi]+vi}  j>=wi;    m[i][j]=m(i+1,j)   0<=j<wi

第二种定义的递归式如下:
                              0                  1
   m[i][j]=max{m[i-1][j],m[i-1][j-wi]+vi}    j>=wi;    m[i][j]=m(i-1,j)   0<=j<wi

代码如下:

0-1背包问题 - johnlxj - DreamHigh #include < stdio.h >
0-1背包问题 - johnlxj - DreamHigh#include
< iostream >
0-1背包问题 - johnlxj - DreamHigh#include
< string .h >
0-1背包问题 - johnlxj - DreamHigh
using   namespace  std;
0-1背包问题 - johnlxj - DreamHigh
0-1背包问题 - johnlxj - DreamHigh
int  max( int  x, int  y)
0-1背包问题 - johnlxj - DreamHigh
{
0-1背包问题 - johnlxj - DreamHigh    
if(x>y)
0-1背包问题 - johnlxj - DreamHigh        
return x;
0-1背包问题 - johnlxj - DreamHigh    
return y;
0-1背包问题 - johnlxj - DreamHigh}

0-1背包问题 - johnlxj - DreamHigh
0-1背包问题 - johnlxj - DreamHigh
int  min( int  x, int  y)
0-1背包问题 - johnlxj - DreamHigh
{
0-1背包问题 - johnlxj - DreamHigh    
if(x>y)
0-1背包问题 - johnlxj - DreamHigh        
return y;
0-1背包问题 - johnlxj - DreamHigh    
return x;
0-1背包问题 - johnlxj - DreamHigh}

0-1背包问题 - johnlxj - DreamHigh
0-1背包问题 - johnlxj - DreamHightemplate 
< class  Type >      
0-1背包问题 - johnlxj - DreamHigh
void  Knapsack(Type  * v, int   * w, int  c, int  n,Type m[][ 20 ]) // 构造m,最优取舍方案函数!!
0-1背包问题 - johnlxj - DreamHigh
{
0-1背包问题 - johnlxj - DreamHigh    
int i,j;
0-1背包问题 - johnlxj - DreamHigh    
int jMax=min(w[n]-1,c);
0-1背包问题 - johnlxj - DreamHigh
0-1背包问题 - johnlxj - DreamHigh    
for(j=0;j<=jMax;j++)
0-1背包问题 - johnlxj - DreamHigh        m[n][j]
=0;
0-1背包问题 - johnlxj - DreamHigh
0-1背包问题 - johnlxj - DreamHigh    
for(j=w[n];j<=c;j++)
0-1背包问题 - johnlxj - DreamHigh        m[n][j]
=v[n];
0-1背包问题 - johnlxj - DreamHigh
0-1背包问题 - johnlxj - DreamHigh    
for(i=n-1;i>=1;i--)
0-1背包问题 - johnlxj - DreamHigh    
{
0-1背包问题 - johnlxj - DreamHigh        jMax
=min(w[i]-1,c);
0-1背包问题 - johnlxj - DreamHigh
0-1背包问题 - johnlxj - DreamHigh        
for(j=0;j<jMax;j++)
0-1背包问题 - johnlxj - DreamHigh            m[i][j]
=m[i+1][j];
0-1背包问题 - johnlxj - DreamHigh
0-1背包问题 - johnlxj - DreamHigh        
for(j=w[i];j<=c;j++)
0-1背包问题 - johnlxj - DreamHigh            m[i][j]
=max(m[i+1][j],m[i+1][j-w[i]]+v[i]);
0-1背包问题 - johnlxj - DreamHigh    }

0-1背包问题 - johnlxj - DreamHigh
0-1背包问题 - johnlxj - DreamHigh
/*    m[1][c]=m[2][c];
0-1背包问题 - johnlxj - DreamHigh    if(c>=w[1])
0-1背包问题 - johnlxj - DreamHigh        m[1][c]=max(m[1][c],m[2][c-w[1]]+v[1]);
*/
//这里是书上的一个错误,并不是m[1][c]就是0-1背包问题的解,事实上m[1]上的所有解都有可能!!
0-1背包问题 - johnlxj - DreamHigh    
//所以还是应该把m[1]上的所有最优构造都算出来,然后去最大值
0-1背包问题 - johnlxj - DreamHigh
}

0-1背包问题 - johnlxj - DreamHigh
0-1背包问题 - johnlxj - DreamHightemplate 
< class  Type >                              // 构造x数组函数
0-1背包问题 - johnlxj - DreamHigh
void  Traceback(Type m[][ 20 ], int   * w, int  c, int  n, int  x[])
0-1背包问题 - johnlxj - DreamHigh
{
0-1背包问题 - johnlxj - DreamHigh    
int i;
0-1背包问题 - johnlxj - DreamHigh    
for(i=1;i<n;i++)
0-1背包问题 - johnlxj - DreamHigh    
{
0-1背包问题 - johnlxj - DreamHigh        
if(m[i][c]==m[i+1][c])
0-1背包问题 - johnlxj - DreamHigh            x[i]
=0;
0-1背包问题 - johnlxj - DreamHigh        
else
0-1背包问题 - johnlxj - DreamHigh        
{
0-1背包问题 - johnlxj - DreamHigh            x[i]
=1;
0-1背包问题 - johnlxj - DreamHigh            c
-=w[i];
0-1背包问题 - johnlxj - DreamHigh        }

0-1背包问题 - johnlxj - DreamHigh    }

0-1背包问题 - johnlxj - DreamHigh
0-1背包问题 - johnlxj - DreamHigh    x[n]
=(m[n][c])?1:0;
0-1背包问题 - johnlxj - DreamHigh}

0-1背包问题 - johnlxj - DreamHigh
int  main()
0-1背包问题 - johnlxj - DreamHigh
{
0-1背包问题 - johnlxj - DreamHigh    
int w[10],v[10],x[10],m[20][20],c,n,max,c0;
0-1背包问题 - johnlxj - DreamHigh    
int i,j;
0-1背包问题 - johnlxj - DreamHigh
0-1背包问题 - johnlxj - DreamHigh    
while(scanf("%d",&n)!=EOF)
0-1背包问题 - johnlxj - DreamHigh    
{
0-1背包问题 - johnlxj - DreamHigh        max
=0;
0-1背包问题 - johnlxj - DreamHigh        memset(m,
0,sizeof(m));
0-1背包问题 - johnlxj - DreamHigh        
for(i=1;i<=n;i++)
0-1背包问题 - johnlxj - DreamHigh        
{
0-1背包问题 - johnlxj - DreamHigh            scanf(
"%d %d",&w[i],&v[i]);
0-1背包问题 - johnlxj - DreamHigh        }

0-1背包问题 - johnlxj - DreamHigh        scanf(
"%d",&c);
0-1背包问题 - johnlxj - DreamHigh
0-1背包问题 - johnlxj - DreamHigh        Knapsack(v,w,c,n,m);    
//构造最优取舍方案
0-1背包问题 - johnlxj - DreamHigh
        
0-1背包问题 - johnlxj - DreamHigh        
for(i=1;i<=c;i++)
0-1背包问题 - johnlxj - DreamHigh        
{
0-1背包问题 - johnlxj - DreamHigh            
if(m[1][i]>max)
0-1背包问题 - johnlxj - DreamHigh            
{
0-1背包问题 - johnlxj - DreamHigh                max
=m[1][i];
0-1背包问题 - johnlxj - DreamHigh                c0
=i;
0-1背包问题 - johnlxj - DreamHigh            }

0-1背包问题 - johnlxj - DreamHigh        }

0-1背包问题 - johnlxj - DreamHigh        Traceback(m,w,c0,n,x);        
//构造x数组
0-1背包问题 - johnlxj - DreamHigh
        
0-1背包问题 - johnlxj - DreamHigh        printf(
"最优矩阵如下:\n");
0-1背包问题 - johnlxj - DreamHigh        
for(i=1;i<=n;i++)
0-1背包问题 - johnlxj - DreamHigh        
{
0-1背包问题 - johnlxj - DreamHigh            
for(j=0;j<=c;j++)
0-1背包问题 - johnlxj - DreamHigh                printf(
"%d ",m[i][j]);
0-1背包问题 - johnlxj - DreamHigh            printf(
"\n");
0-1背包问题 - johnlxj - DreamHigh        }

0-1背包问题 - johnlxj - DreamHigh        
0-1背包问题 - johnlxj - DreamHigh        printf(
"方案如下:\n");
0-1背包问题 - johnlxj - DreamHigh        
for(i=1;i<=n;i++)
0-1背包问题 - johnlxj - DreamHigh            printf(
"%d ",x[i]);
0-1背包问题 - johnlxj - DreamHigh        printf(
"\n");
0-1背包问题 - johnlxj - DreamHigh    }

0-1背包问题 - johnlxj - DreamHigh    
return 0;
0-1背包问题 - johnlxj - DreamHigh}

运行结果如下:

    
               第二种递归思路下的代码和运行过程我就不写,就初始化和递归次序不同!!
               我一个同学经常跟我说,以后自己有孩子,一个赚了1000给我花100,一个赚了10000给我花200,我还是跟着赚1000的吧!!其实问题不在别人,而在自己,努力就成!!!我受益匪浅。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

johnlxj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值