My Sixty-seventh Page - 0-1背包问题理论 - By Nicolas
创始人
2024-02-08 04:34:14

小尼在这里跟大家说明一下0-1背包问题的理论,首先我们需要认识一下什么是背包问题。小尼在这里拉一下代码随想录的代码,有兴趣的小伙伴也想把背包问题学好,可以去代码随想录看一看背包问题的讲解,也可以去B站看一看代码随想录对背包问题的讲解:
416.分割等和子集1

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

动态规划-背包问题

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

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

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

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

我们既然将背包问题当成动态规划的问题进行对应的求解,那么我们就一定存在递归五部曲,小尼一一说明一下这五部的进行,首先第一步:确定dp数组以及下标的含义

对于背包问题,我们先讲第一种写法,就是利用二维数组,即dp[i][j]表示从下表为[0-i]的物品里面任意取,放进容量为j的背包里面,价值总和的最大是多少,所以小伙伴一定要搞清楚,dp在这里表示的是价值的多少,也就是在i,j同时满足的条件下得到的价值的最优解

第二步:递推公式

我们回顾一下dp数组的含义,就是从下标为[0-i]的物品里面任意取,放进容量为j的背包,价值总和最大时多少,我们先需要分析放入的情况:

1、我们不放入物品:由dp[i-1][j]推出,即背包容量为j,里面不放入物品i的最大价值,此时dp[i][j]就是dp[i-1][j]。(其实就是当物品i的重量大于背包j的重量时,物品i无法放入背包中,所以背包内的价值依然和前面的相同)

2、我们放入物品:由dp[i-1][j-weight[i]]可以推出,dp[i-1][j-weight[i]]为背包容量为j-weight[i]的时候不放入物品i的最大价值,那么dp[i-1][j-weight[i]] + value[i](物品i的价值),就是背包放物品i得到的最价值,所以递归的公式为:dp[i][j] = max(dp[i-1][j], dp[]i-1[j-weight[i]] + value[i])

第三步:对dp数组进行初始化

首先我们从dp[i][j]的定义出发,如果背包容量j为0的话,即dp[i][0],无论是选取哪些物品,背包价值总和一定为0。对于小尼所说的上述的二维数组的情况也只需要给出这一个初始化就可以了。

第四步:确定遍历顺序

在本层的条件下,我们无论是从物品的角度进行遍历或者是从背包容量的大小进行遍历都是可以的。小尼接下来就给出先遍历物品,然后遍历背包重量的代码:

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

小尼接下来再给出先遍历背包,再遍历物品的代码:

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

第五步:导出背包放入的顺序

最后我们只需要导出顺序即可

小尼接下来给出一段一个背包的完整的代码:

public static void main(String[] args) {int[] weight = {1, 3, 4};int[] value = {15, 20, 30};int bagsize = 4;testweightbagproblem(weight, value, bagsize);}public static void testweightbagproblem(int[] weight, int[] value, int bagsize){int wlen = weight.length, value0 = 0;//定义dp数组:dp[i][j]表示背包容量为j时,前i个物品能获得的最大价值int[][] dp = new int[wlen + 1][bagsize + 1];//初始化:背包容量为0时,能获得的价值都为0for (int i = 0; i <= wlen; i++){dp[i][0] = value0;}//遍历顺序:先遍历物品,再遍历背包容量for (int i = 1; i <= wlen; i++){for (int j = 1; j <= bagsize; j++){if (j < weight[i - 1]){dp[i][j] = dp[i - 1][j];}else{dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i - 1]] + value[i - 1]);}}}//打印dp数组for (int i = 0; i <= wlen; i++){for (int j = 0; j <= bagsize; j++){System.out.print(dp[i][j] + " ");}System.out.print("\n");}}

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...