java编程背包题目求组合_[编程题]【动态规划】背包问题

[编程题]【动态规划】背包问题

题目信息

问题:现有背包。其中有四个商品。价值-体积如下

* 物品编号: 1 2 3 4

* 物品体积: 2 3 4 5

* 物品价值: 3 4 5 6

* 问:如何才能保证在背包容量为8的情况下装的价值最大?

思路

背包问题,动态规划

思路

1、构建dp表,dp【i】【j】代表该i编号的背包为止容量为j的最大价值。先填表加深理解。

2、填完表如果要找出价值为k的容量的背包加入的物品标号只需要从i=dp.length-1,j=k的dp数组元素处回溯。

填完表如下(借视频中up主的结果):

f06f48c30d0be5701eb69f7f3df7da91.png

总结结论如下(借视频中up主的总结):

265f166ea4559e0910e6a7c066eacc5a.png

理解了上述总结的思路,其实代码就很容易写出来了。

代码如下

Java代码

package interviewcode;

import java.lang.annotation.Target;

import java.util.ArrayList;

import java.util.Arrays;

/**

* @author

* @create 2020/8/11 - 10:52

* @descp:

* 问题:现有背包。其中有四个商品。价值体积如下

* 物品编号: 1 2 3 4

* 物品体积: 2 3 4 5

* 物品价值: 3 4 5 6

* 问:如何才能保证在背包容量为8的情况下装的价值最大?

*

* 步骤1:填表之后的结果:

* 000000000

* 003333333

* 003447777

* 003457899

* 0034578910

* 步骤2:回溯

*/

//方法:动态规划

public class P28_背包问题 {

public static void main(String[] args) {

int[] size = new int[]{0,2,3,4,5}; //第0位放一个默认的0值,为了下边方便取size[i]就为i号物品的体积

int[] money = {0,3, 4, 5, 6}; //第0位放一个默认的0值,为了下边方便取money[i]就为i号物品的价值

int target = 14; //指定的背包大小

//调用

int[][] ints = dpWrite(size, money, target);

ArrayList huisu = huisu(ints, size, target);

System.out.println("您输入的背包大小是:"+target);

System.out.println("添加的物品编号是:"+huisu);

System.out.println("最大价值:"+ints[size.length-1][target]);

}

public static int[][] dpWrite(int[] size,int[] money,int targetValue){

//这里构造一个例如4*8的dp,行代表截止到i背包的最优组合的价值,j代表的背包的容量值

int[][] dp = new int[size.length][targetValue+1];

//初始化第0行的值

for(int j=0;j<=targetValue;j++){

dp[0][j] = 0;

}

//初始化第一列的值

for(int i=1;i

dp[i][0] = 0;

//dp[i][1] = 0;

}

//初始化中间值i

for(int i=1;i

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

//如果第i号背包的体积小于当前的j背包容量,就保持和dp[i-1]值相同,即没放入

if(size[i]>j){

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

}else{

/*即如果当前i号物品体积可以放入的话,就看预留该体积后剩余的价值在i-1号物品中的最大值加上该物品的价值和是否

是大于dp[i-1][j]的值,谁大取谁*/

dp[i][j] = Math.max(dp[i-1][j-size[i]>0?j-size[i]:0]+money[i],dp[i-1][j]);

}

}

}

//这样就填表完成了。剩下的就是需要回溯取出看对应某价值target的物品组合是什么

//先打印一下填的表

/*for (int i = 0; i < dp.length; i++) {

for (int j = 0; j < dp[i].length; j++) {

System.out.print(dp[i][j]+"\t");

}

System.out.println();

}*/

return dp;

}

public static ArrayList huisu(int[][] dp,int[] size, int t){

ArrayList res = new ArrayList<>();

int i = dp.length-1;

int j = t;

while (i>0 || j>0){

if(dp[i][j]==dp[i-1][j]){

i--;

}else{

res.add(i);

j = j-size[i];

i--;

}

}

return res;

}

}

输出:

测试1:例如:背包容量8,输出物品编号和可以获得的最大价值:

6c72f38a577a0ced9f1742a97fc2321d.png

测试2:例如:背包容量14,输出物品编号和可以获得的最大价值:

4ec3e3ed64cc908f5fe78bd83b59713d.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值