我昨天深夜刚到家,昨天早上我还在收拾行李。因为我家比学校要冷得多,所以我要尽可能多带衣服回去,严格来说应该是保证装入背包的衣服的总体积最大(毕竟体积越大也就是厚度越大,越暖和嘛),那么我要选择哪些衣服装入背包呢?
分析问题
衣服只有两种状态,要么装入背包,要么不装,既然如此那就太简单了,这不就是传说中的01背包问题吗?实际上并不完全是之前接触的01背包问题,之前的01背包问题是这样的:有n个物品,第i个物品的重量是w[i],价值是v[i],背包最大载重为c,装入哪些物品可以使总价值最大?对我来说我完全可以把价值换成体积一样去处理,到底哪里不一样?是因为背包最大容量有限制啊,体积不能做到越大越好!这可咋办?实际上很简单,我只需要先假设背包体积无上限,重量有上限,把价值换成体积,当做之前接触过的01背包问题,使用动态规划求解。因为动态规划是不断地填表,这个表中的每一个解都是子问题的最优解。我只需要在这个表中筛选出来一个值,这个值满足两个条件:1.最接近背包最大容量。2.没有超过背包最大容量。我之所以要使用这种很简单的方法,是因为如果我把体积也考虑进去它就变成了一个三维01背包问题,就需要一个三维的表来存放最优解了,空间复杂度n3!
解决问题
这个问题总共分为两大步,先解决01背包问题,然后再去筛选符合条件的最优解。下面我们先来看01背包问题。
01背包问题
01背包问题的解决方式有很多种:动态规划,回溯……在这里因为背包最大载重和衣服数量比较小,使用动态规划是可以的,空间上不会耗费太多。
用动态规划求解01背包问题很简单,就一个公式:f[i, j] = max{f[i-1, j-w[i]]+v[i](j >= w[i]), f[i-1, j]}
f[i, j]表示在前i件衣服中选择若干件放在承重为j的背包中,可获取的最大体积,w[i]是第i件衣服的重量,v[i]是第i件衣服的体积。问题变成了为了保证总体积的最大化,第i件衣服要不要装入背包?下面我来根据我当时的情况,简单的举个例子。
假设我当时共有a,b,c,d,e这5件衣服,它们的重量分别是2,2,6,5,4,它们的体积分别是6,3,5,4,6,现在给你个承重为10的背包,怎么装背包,可以保证体积最大。
为了方便大家理解,下面先来结合公式手工填表(要填两张表,一个是最优值表,一个是最优决策表),首先要明确的是这个表是自上向下,自左向右的。直接给出答案,填表的过程我就不详细讲解了,因为太繁琐了。
name | weight | volume | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
a | 2 | 6 | 0 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 |
b | 2 | 3 | 0 | 6 | 6 | 9 | 9 | 9 | 9 | 9 | 9 | 9 |
c | 6 | 5 | 0 | 6 | 6 | 9 | 9 | 9 | 9 | 11 | 11 | 14 |
d | 5 | 4 | 0 | 6 | 6 | 9 | 9 | 9 | 10 | 11 | 13 | 14 |
e | 4 | 6 | 0 | 6 | 6 | 9 | 9 | 12 | 12 | 15 | 15 | 15 |
name | weight | volume | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
a | 2 | 6 | a | a | a | a | a | a | a | a | a | |
b | 2 | 3 | a | a | ab | ab | ab | ab | ab | ab | ab | |
c | 6 | 5 | a | a | ab | ab | ab | ab | ac | ac | abc | |
d | 5 | 4 | a | a | ab | ab | ab | ad | ac | abd | abc | |
e | 4 | 6 | a | a | ab | ab | ae | ae | abe | abe | abe |
找出符合条件的最优解
因为背包容量受到限制,所以并不是体积越大越好。假设背包容量为10,那么我们一眼就能够从第一个表中找出符合条件的值——就是10,然后就是对应到第二张表找到最优决策——ad!
今天的文章有不懂的可以加群,群号:822163725,备注:小陈学Python,不备注可是会被拒绝的哦~!