0、1背包问题的核心代码详解~

0,1背包问题详解

今天面了华为,让解释笔试题代码,是一个0/1背包问题,之前应该是处于一个会写代码,但是理解的不通透的状态,所以下定决心一定要把0/1背包问题解释明白。由于水平有限,讲解不了官方答案什么动态规划,分治法等就不细说了,只讲自己对0、1背包问题核心代码的理解。

题目描述:一辆卡车容量为C,要把n个箱子运往目的地,每个箱子的体积为Vi,价值为Wi,要使卡车能够运载的箱子的总价值最大,怎么选择该运送哪些箱子。
解释:就是说虽然把箱子全部装上卡车总价值是最大的,但是卡车容量有限,在不超过卡车容量的前提下,需要把总价值最大的一组箱子装上这个卡车,让你选出这一组箱子,求这个最大的总价值。

这是一个典型的0、1背包问题,为了满足“不大于卡车容量”这个约束条件,我们需要对每一个箱子做一个选择,装上卡车或者不装上卡车。如果第i个箱子被选择装上卡车,那么总价值就包括这个箱子的价值,同时卡车的容量也会相应的减少,肯定有的箱子就会装不进来了,所以每装一个箱子都需要判断,这箱子能带来的总价值顶不顶得上它占用的卡车的那部分容量。(举例:三个箱子,第一个体积为6,价值为10;第二个体积为3,价值为4,;第三个体积为4,价值为5;卡车容量为8 。显然你选择往卡车上装了第一个箱子,后面两个箱子就没有足够的体积待了;这个时候你就需要判断,第一个箱子的价值是不是大于被他挤掉的另外两个箱子的总价值,如果大得话,很显然,就会选择把第一个箱子装上卡车;如果不大的话,就不要让第一个箱子来占用卡车的体积了,就把卡车的体积留给其他更有价值的箱子吧) 好啦,讲到这里,分析就结束了,那我们来看这道题的程序,一边看一边做具体分析。

程序分析:

for (int i=1; i < n+1; i++) {
	for (int j=1; j < C+1; j++) {
		if(V[i] > c[j]){
			total_value[i][j] = total_value[i - 1][j];
	}
	    else{
		    total_value[i][j] = max(total_value[i-1][j], total_value[i - 1][j-V[i]] + W[i]);
    }
}

n表示箱子的个数,C代表卡车的容量;先说一下为什么做这样一个两层的for循环。由于这是一个求最优解的问题,并且发现最终的最优解对应着前面的每一步都必须是最优解,所以我对前面所有的情况都需要求出最优解,一步一步找到最终的最优解。这样循环的意思是:当i = 1, j = 2时;一个箱子,卡车容量是2,那么如果这个箱子可以的体积大于卡车的容量,这个箱子不能装上卡车,所以卡车能运载的最大价值为0,也就是对应代码中的if条件语句,这种情况下的总价值=total_value[i-1][j],由于我们在一开始把这个二维矩阵的第一行和第一列都设置为0了,(第一行 n =0 对应没有箱子,所以价值为0;第一列 j = 0 对应卡车允许占用的容量为0,无法装载任何一个箱子,所以总价值也为0。)再考虑一种情况,当i = 3, j = 10 的时候,也就是说现在要判断第三个箱子能不能装上卡车,要求这个时候卡车可以被占用的容量是10。首先就要判断这第三个箱子能不能装上卡车,如果第三个箱子的体积大于卡车当前能够被占用的容量10,那么这个箱子肯定不能装上车,那么此时最大的价值 = 判断第二个箱子能不能被装上车时,并且当时卡车能被占用的容量也是10的时候的最大总价值(仔细理解这句话哦,你这个箱子不能被装载到卡车上,所以相当于我不占用卡车的容量,那我就是把所有的容量10都让给别的箱子了哦,所以别的箱子(就是前[i-1]个箱子的组合),允许占用的卡车容量是10!!!),所以他们最大的价值是total_value[i-1][j],这里的j=10。也就是if添加语句里面的total_value[i][j] = total_value[i - 1][j];;另一种情况就是else条件语句,如果当前的箱子体积小于卡车能够被占用的容量,这个箱子能够装上卡车,那么我们需要做的就是选择装或者不装它;问题来了,我们该怎么选择呢???上面已经解释过简单的情况了,现在我们重新来解释一下:如果选择把这个箱子装上卡车,那么这个箱子势必会占用当前卡车总容量10 的一部分,所以留给其他箱子的容量只剩下(10 - 当前箱子的体积)了,总的价值就是当卡车容量是(10 - 当前箱子的体积)的时候,能够装载的箱子的总价值 + 当前箱子的价值!!!也就是这样total_value[i][j] = total_value[i - 1][j-V[i]] + W[i],如果选择不把这个箱子装上卡车,那么卡车的容量10都会留给其他箱子,那么这个时候总价值 = 前面 i - 1 的箱子在判断的时候,并且卡车容量为10 的时候的总价值total_value[i-1][j],即total_value[i][j] = total_value[i-1][j];所以二者选更大的,就有了这行代码total_value[i][j] = max(total_value[i-1][j], total_value[i - 1][j-V[i]] + W[i]);

最后

讲了0、 1 背包问题的核心代码,一定一定要弄清楚else 条件语句中的那行代码呀!为什么二者选最大,这二者又是怎么来的!!!不知道有没有给大家讲明白,反正我是明白啦~哈哈哈,好像又开心了呢,不管怎样,找工作还是要继续呀,也祝大家学代码学的开心!!!

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值