背包问题算法设计

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

背包问题算法设计

题目描述:

有n个物品,每个物品的重量为w[i],取物品则效益增加p[i],对于给定的一个能容纳重量为M的背包,怎样装包才能使获得的效益最大?每个物品的取值为x[i],x[i]=0/1,0表示该物品不装包,1表示将该物品装入包中。

以上描述就是一个经典的0/1背包问题。

输入输出:

输入一个n,然后输入w[1,2,...,n],p[1,2,...,n]

输出最大效益值和x[1,2,...,n]用0/1表示

sampleinput

3//n

234//w[i]

125//p[i]

sampleoutput

6//最大效益值

101//x[i]

解题思路:

假定决策次序为x[n],x[n-1],...,x[1]。在对x[n]做出决策之后,问题处于下列两种状态之一:

背包的剩余容量为M,没有产生任何效益;

剩余容量是M-w,效益增长了p。

显然,余下来的x[n-1],x[n-2],..,x[1]的决策相对于x所产生的问题状态应该是最优的,否则x[n],x[n-1],...,x[1]就不能是最优决策序列。

设f[j][x]是从物品1-j,背包容量为x的最优解

则最优序列的解f[n][m]

对于任意的f[i][x]=max{f[i-1][x],f[i-1][x-wi]+pi}---------------------------(1)

为了能向后递推而最后求出f[n][m],需要从f[0][x]开始。对于所有x>=0,有f[0][x]=0,

当x<0时,有f[0][x]=负无穷。根据(1)马上可解出0<=x=w1的情况下f[1][x]的值。

接着又可以不断递推出f[2],f[3],...,f[n]在x相应的取值范围内的值。

于是有求f[n][m]的算法:

for(i=1;i<=n;i++)

{

for(j=1;j<=m;j++)

{

if(j-w[i]>=0)

f[i][j]=MAX(f[i-1][j],f[i-1][j-w[i]]+p[i]);

else

f[i][j]=f[i-1][j];

}

一般而言,背包问题是要求一个最优值,如果要求输出这个最优值的方案,可以参照一般动态规划问题输出方案的方法:记录下每个状态的最优值是由状态转移方程的哪一项推出来的,换句话说,记录下它是由哪一个策略推出来的。便可根据这条策略找到上一个状态,从上一个状态接着向前推即可。

设g[i][v]=0表示推出f[i][v]的值时是采用了方程的前一项(也即f[i][v]=f[i-1][v]),g[i][v]表示采用了方程的后一项。注意这两项分别表示了两种策略:未选第i个物品及选了第i个物品。

于是改写求f[n][m]的过程为:

for(i=1;i<=n;i++)

{

for(j=1;j<=m;j++)

{

if(j-w[i]>=0)

{

f[i][j]=MAX(f[i-1][j],f[i-1][j-w[i]]+p[i]);

if(f[i][j]==f[i-1][j-w[i]]+p[i])

g[i][j]=1;

}

else

f[i][j]=f[i-1][j];

}

}

那么求方案的向量的伪代码可以这样写i=n;

j=m;

while(i>0)

{

if(g[i][j]==0)

x[i]=0;

else

{

x[i]=1;

j=j-w[i];

}

i--;

}

最后输出向量x和f[n][m]既可。

算法空间分析:

时间复杂度O(n*m)

时间复杂度O(n*m)

代码设计:

#include usingnamespacestd;

#defineN200

#defineMAX(a,b)(a>b?a:b) intmain()

{

intn,m,i,j;

intw[N],p[N],x[N];

intf[N][N],g[N][N]; freopen("in.txt","r",stdin); while(cin>>n>>m)

{

for(i=1;i<=n;i++)

cin>>w[i];

for(i=1;i<=n;i++)

cin>>p[i];

memset(f,0,sizeof(f)); memset(g,0,sizeof(g));

for(i=1;i<=n;i++)

{

for(j=1;j<=m;j++)

{

if(j-w[i]>=0)

{

f[i][j]=MAX(f[i-1][j],f[i-1][j-w[i]]+p[i]); if(f[i][j]==f[i-1][j-w[i]]+p[i])

g[i][j]=1;

}

else

f[i][j]=f[i-1][j];

}

}

i=n;

j=m;

while(i>0)

{

if(g[i][j]==0)

x[i]=0;

else

{

x[i]=1;

j=j-w[i];

}

i--;

}

for(i=1;i<=n;i++) cout<

cout<

cout<

return0;

}

相关文档
最新文档