二维dp数组01背包

题目

有N件物品和一个最多能被重量为W 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。

图片

这是标准的背包问题,以至于很多同学看了这个自然就会想到背包,
甚至都不知道暴力的解法应该怎么解了。

这样其实是没有从底向上去思考,而是习惯性想到了背包,
那么暴力的解法应该是怎么样的呢?

每一件物品其实只有两个状态,取或者不取,所以可以使用回溯法搜索出所有的情况,
那么时间复杂度就是O(2^n),这里的n表示物品数量。

所以暴力的解法是指数级别的时间复杂度。进而才需要动态规划的解法来进行优化!

举一个例子:

背包最大重量为4。

物品为:


       重量	价值
物品0	1	15
物品1	3	20
物品2	4	30
问背包能背的物品最大价值是多少?

解题思路与算法

  • 确定递推表达式:确定dp数组及其下标含义:dp[i][j]表示从0 - i中任意取放入容量为j的背包得到的最大价值 ;
    • 可以不取第i个或取第i个使得背包价值最大,
    • 即dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-value[i]])
  • dp数组的初始化:若dp[i][j]中的j也就是背包容量为0,那么总价值dp[i][0]一定为0;若dp[i][j]中的i为0,也就是只取第0个物品放进背包里
    • if(j>=value[0]) 那么说明背包容量足够大能装下第0个物品dp[0][j-value[0]]
    • 则可以倒序遍历初始化dp数组,
    • for(int j=w;j>=weight[0];j–){dp[0][j]=dp[0][j-weight[i]]+value[i];}
  • 确定遍历顺序:由递推表达式得有i-1,所有从前向后遍历

代码

public int zero_one_bag() {
		int[] weight = {1, 3, 4};
	    int[] value = {15, 20, 30};
	    int bagWeight = 4;

	    // 二维数组
	    int[][] dp=new int[weight.length+ 1][bagWeight + 1];

	    // 初始化 
	    for (int j = bagWeight; j >= weight[0]; j--) {
	        dp[0][j] = dp[0][j - weight[0]] + value[0];
	    }

	    // weight数组的大小 就是物品个数
	    for(int i = 1; i < weight.length; i++) { // 遍历物品
	        for(int j = 0; j <= bagWeight; j++) { // 遍历背包容量
	            if (j < weight[i]) {
	            	dp[i][j] = dp[i - 1][j];
	            }
	            else {
	            	dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
	            }

	        }
	    }

	    return dp[weight.length - 1][bagWeight];
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值