0-1背包问题 动态规划java_动态规划之0-1背包问题

本文介绍了如何使用动态规划解决0-1背包问题。通过建立二维数组m[i][j]来表示考虑前i件物品时,背包容量为j的最大价值。通过递归关系式更新数组,并通过回溯确定物品的装入情况。最后,提供了Java代码实现整个过程。
摘要由CSDN通过智能技术生成

m[i][j]表示当可以放入前i件物品且背包容量为j时的最大价值。当只能放入第一件物品即i=0时:若背包容量j=w[0]时,物品可以放入背包,此时m[0][j]=v[0]。当可以放入前2件物品即i=1时,我们需要进行这样的处理:若j=w[1]时,假设此时背包容量j=8,第二件物品可以被放入背包内,那么便会出现两种情况:

(1)将第二件物品放入背包,那么背包中物品的最大价值是多少呢?因为第二件物品重量为w[1]=2,在将第二件物品放入背包之前,背包的容量应为j-w[1]=8-2=6,此时背包的最大价值是m[0][6],因此若将第二件物品放入背包,其背包的最大价值m[1][j]=m[0][j-w[1]]+v[1];

(2)不将第二件物品放入背包,那么此时背包中物品的最大价值依然为只放入第一件物品时背包的最大价值,即m[1][j]=m[0][j];

我们选取(1)(2)中价值的较大者作为i=1,j=8时背包中的最大价值。

i=2,3,4时的分析同上,直到背包的容量为10,此时m[4][10]即为背包中物品的最大价值。

有了上面的分析,我们很容易写出下面的递归关系:

(1)i=0  当j=w[0]时,m[0][j]=v[0]。

(2)i>0  当j=w[i],m[i][j]=max{m[i-1][j-w[i]]+v[i],m[i-1][j]}。

得到了满足约束条件的背包中物品的最大价值后,需要知道是哪些物品被放入了背包。观察二维表m[i][j],我们注意到m[i][c]表示当背包重量为题目中要求的c时背包的最大价值,那么在得到m[i][c]之前,我们必然是比较了m[i-1][j-w[i]]+v[i]与m[i-1][j]的大小,从而决定是否将物品放入背包。所以我们可以利用回溯的方法,若m[i][j]=m[i-1][j],那么物品没有放入背包;否则物品一定被放入背包。因此我们可以从最后一件物品开始,一步一步回退到第一件物品,直到找到所有的物品放入背包的情况。本题中物品的装入情况如表中红色和蓝色部分所示,其中红色表示当前物品被装入背包,蓝色表示没有装入背包。

代码实现:

public class Main {

public static void main(String[] args) {

int []w={2,2,6,5,4}; //物品重量

int []v={6,3,5,4,6}; //物品价值

int c=10; //背包容量

int []x=new int[5]; //记录物品装入情况,0表示不转入,1表示装入

x[0]=1; //初始值表示第一个物品已装入背包

int [][]m=new int[5][c+1];//需要维护的二维表,为了方便计算加入一列,其中第0列表示背包容量为0时背包的最大价值为0

/*

* 初始化第一行,即背包中装入第一件物品

* */

for(int j=1;j<=c;j++){

if(j>=w[0]){

m[0][j]=v[0];

}

}

/*

* 背包中依次装入其他的物品

* */

for(int i=1;i<5;i++){

for(int j=1;j<=c;j++){

if(j

else{

if(m[i-1][j-w[i]]+v[i]>m[i-1][j]) m[i][j]=m[i-1][j-w[i]]+v[i]; //选择价值较大者

else m[i][j]=m[i-1][j];

}

}

}

System.out.println("背包的最大价值为:"+m[w.length-1][c]);

for(int i=4;i>=1;i--){

if(m[i][c]>m[i-1][c]){

x[i]=1; //装入背包

c-=w[i]; //物品i装入背包之前背包的容量

}

else x[i]=0; //没有装入背包

}

System.out.print("装入背包的物品编号是:");

for(int i=0;i<5;i++){

if(x[i]==1) System.out.printf("%2d",(i+1));

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值