01背包+完全背包问题
2016-09-24 17:16
246 查看
背包问题已经有很多写得很好的博客,这里的背包问题只是一个个人学习总结,希望能够把问题说得更明白清楚易懂。
贴下背包九讲问题的优秀博客网址:
http://blog.csdn.net/pi9nc/article/details/8142876
PART1:01背包问题
题目:有N件物品,第i件物品的价值为value[i],重量为weight[i],求解将哪些物品装入背包可使价值总和最大,注意每件物品只可以装一次。
这里我们仍然以一个例子来看这个算法。
有一个能够承载10kg的小推车,商店中有如下物品:
那么我们现在研究一下,怎样才能让背包中物品的价值尽可能大。我们必须要有一个正确的思路,这是解题的关键。
设W[i][j]表示在背包可容纳重量j,只装序号不大于i的物品时,背包可装入物品的最大价值,value对应于各个物品的价值,weight对应于各个物品的重量。
算法DP公式:W[i][j] = max{如果装序号为i的物品,如果不装序号为i的物品}
=max{W[i-1][j-weight[i]]+value[i] , W[i-1][j]}
算法很简单,也很容易理解,我们不难发现算法的时间复杂度为O(N*V),空间消耗就是用了个二维数组。这里可以优化的地方就是我们不使用二维数组,使用一维数组来解决这个问题。
那么我们设一维数组为array
算法:我们先对A物品分析,找出只装A物品的情况的array
;
再添加一个B物品进行分析,我们之前已经把A物品的所有的array值都算出来了,所以可以把包含A、B物品的array
算出来;
同理直至到E物品,我们就算出来了结果为array
。
那么难点在哪里呢?难点在于每个物品最多只能装一个。
我们对只装A物品进行分析:
<—————————–我们需要将array数组初始化为零——————————>
注意:我们这个表应该从10往1生成,只有这样才能保证A物品最多只装了1个,否则结果是多个,生成的错误的表如下:
注意到这一点就没有别的什么问题了,现在贴上这道题的c语言代码:
PART2:完全背包问题
题目:有N种物品,第i件物品的价值为value[i],重量为weight[i],求解将哪些物品装入背包可使价值总和最大,注意每种物品可重复装入。
如果看懂了我们上面的01背包问题,你会发现这个问题很简单,只需要我们对01背包的算法进行一丁点改变即可——就是上面说生成错误表的地方,我们就按照那种“错误”的方式生成即可得到完全背包的答案。代码该边就是在第二个循环的地方j从weight[i]到10算array数组。此处无庸赘述。
贴下背包九讲问题的优秀博客网址:
http://blog.csdn.net/pi9nc/article/details/8142876
PART1:01背包问题
题目:有N件物品,第i件物品的价值为value[i],重量为weight[i],求解将哪些物品装入背包可使价值总和最大,注意每件物品只可以装一次。
这里我们仍然以一个例子来看这个算法。
有一个能够承载10kg的小推车,商店中有如下物品:
序号 | 物品 | 重量(weight) | 价值(value) |
---|---|---|---|
1 | A | 2 | 6 |
2 | B | 2 4000 | 3 |
3 | C | 5 | 10 |
4 | D | 4 | 7 |
5 | E | 3 | 4 |
设W[i][j]表示在背包可容纳重量j,只装序号不大于i的物品时,背包可装入物品的最大价值,value对应于各个物品的价值,weight对应于各个物品的重量。
算法DP公式:W[i][j] = max{如果装序号为i的物品,如果不装序号为i的物品}
=max{W[i-1][j-weight[i]]+value[i] , W[i-1][j]}
算法很简单,也很容易理解,我们不难发现算法的时间复杂度为O(N*V),空间消耗就是用了个二维数组。这里可以优化的地方就是我们不使用二维数组,使用一维数组来解决这个问题。
那么我们设一维数组为array
算法:我们先对A物品分析,找出只装A物品的情况的array
;
再添加一个B物品进行分析,我们之前已经把A物品的所有的array值都算出来了,所以可以把包含A、B物品的array
算出来;
同理直至到E物品,我们就算出来了结果为array
。
那么难点在哪里呢?难点在于每个物品最多只能装一个。
我们对只装A物品进行分析:
序号 | 物品 | 重量(weight) | 价值(value) |
---|---|---|---|
1 | A | 2 | 6 |
<—————————–我们需要将array数组初始化为零——————————>
背包可以承载的重量 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
可装入的物品的最大价值array[i] | 0 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 |
注意:我们这个表应该从10往1生成,只有这样才能保证A物品最多只装了1个,否则结果是多个,生成的错误的表如下:
背包可以承载的重量 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
可装入的物品的最大价值array[i] | 0 | 6 | 6 | 12 | 12 | 18 | 18 | 24 | 24 | 30 |
注意到这一点就没有别的什么问题了,现在贴上这道题的c语言代码:
#include <stdio.h> #include <string.h> #define N 5 //物品的件数 #define W 10 //背包可容纳的最大重量 #define max(a,b) (a>b?a:b) int main() { int i,j; int array[W+1]; int weight[] = {2,2,5,4,3}, value[] = {6,3,10,7,4}; memset(array, 0, sizeof(array)); for(i=0;i<N;i++){ for(j=W;j>=weight[i];j--){ array[j]=max(array[j],array[j-weight[i]]+value[i]); } } printf("%d\n",array[W]); return 0; }
PART2:完全背包问题
题目:有N种物品,第i件物品的价值为value[i],重量为weight[i],求解将哪些物品装入背包可使价值总和最大,注意每种物品可重复装入。
如果看懂了我们上面的01背包问题,你会发现这个问题很简单,只需要我们对01背包的算法进行一丁点改变即可——就是上面说生成错误表的地方,我们就按照那种“错误”的方式生成即可得到完全背包的答案。代码该边就是在第二个循环的地方j从weight[i]到10算array数组。此处无庸赘述。
相关文章推荐
- 背包问题(01背包和完全背包)
- 经典背包问题 01背包+完全背包+多重背包
- 01背包问题和完全背包问题
- 01背包问题和完全背包问题
- 背包问题——01背包、完全背包、多重背包、混合三种背包问题
- [背包问题] 01背包、完全背包、整数找零
- 01背包问题和完全背包问题
- 背包问题(01背包 + 完全背包 + 多重背包)
- 背包问题(01背包和完全背包)一维数组实现
- ★★★★★背包问题——“01背包”"完全背包"详解及实现(包含背包中具体物品的求解)
- 背包问题---01背包|完全背包(装满背包的方案总数分析及实现)
- 经典背包问题 01背包+完全背包+多重背包
- 经典背包问题 01背包+完全背包+多重背包
- 动态规划:最少硬币找零问题、01背包问题、完全背包问题
- 背包问题(1)——01背包、完全背包、多重背包、混合三种背包问题
- 背包问题---01背包|完全背包(装满背包的方案总数分析及实现)
- 01背包问题和完全背包问题
- 01背包、完全背包、多重背包、混合三种背包问题
- 背包问题入门 01背包和完全背包
- 动态规划-----背包问题-----01背包,完全背包,多重背包