背包问题
2016-01-07 14:39
183 查看
有一个小偷,跑到一户人家去偷东西;
小偷可以偷6样物品,重量分别为:weight[6] = {1,2,2,6,5,4},对应的价值分别为value[6] = {1,6,3,5,4,6};
小偷只背了一个最大容量为10的包;
问:小偷可以偷走的最大价值是多少?
解题思路:
1).找最贵的偷;
2).找装的最多(最轻)的偷;
3).动态规划求得最优值。
动态规划的原理就是:根据前一次的“最优值”计算当前的“最优值”。
具体步骤:
1. 用一个matrix[num][capacity+1]代表背包中一定物品、一定重量的价值。
num为特定物品,capacity为物品的重量从0到10+1(从0开始是为了便于矩阵下标0的统计)。
这个背包初始情况下为0,如下:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 0 0 0 0 0 0 0 0 0 0
(6)2 0 0 0 0 0 0 0 0 0 0 0
(3)2 0 0 0 0 0 0 0 0 0 0 0
(5)6 0 0 0 0 0 0 0 0 0 0 0
(4)5 0 0 0 0 0 0 0 0 0 0 0
(6)4 0 0 0 0 0 0 0 0 0 0 0
2. 在背包中按物品顺序依次放入,首先放入物品1,物品1对应的价值是1;
在这里,有1个逻辑:物品1在重量0<1<10的情况下,其价值都为1。
如下:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 0 0 0 0 0 0 0 0 0 0
(3)2 0 0 0 0 0 0 0 0 0 0 0
(5)6 0 0 0 0 0 0 0 0 0 0 0
(4)5 0 0 0 0 0 0 0 0 0 0 0
(6)4 0 0 0 0 0 0 0 0 0 0 0
3. 然后放入物品2;
在这里,有3个逻辑:
1).物品2在 2<2<10的情况下,其价值都为6;
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 0 6 6 6 6 6 6 6 6 6
2).在累加重量的基础上累加前一次的价值;
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 0 6 7 7 7 7 7 7 7 7
3).用前一次大的价值取代当前小的价值(补充物品1在重量1时的价值);
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 1 6 7 7 7 7 7 7 7 7
本次填值之后,结果如下:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 1 6 7 7 7 7 7 7 7 7
(3)2 0 0 0 0 0 0 0 0 0 0 0
(5)6 0 0 0 0 0 0 0 0 0 0 0
(4)5 0 0 0 0 0 0 0 0 0 0 0
(6)4 0 0 0 0 0 0 0 0 0 0 0
4. 再放入第3个物品2;
在这里,有3个逻辑:
1).物品2在 2<2<10的情况下,其价值都为3;
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 1 6 7 7 7 7 7 7 7 7
(3)2 0 0 3 3 3 3 3 3 3 3 3
2).在累加重量的基础上累加前一次的价值;
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 1 6 7 7 7 7 7 7 7 7
(3)2 0 0 3 3 9 10 10 10 10 10 10
3).用前一次大的价值取代当前小的价值;
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 1 6 7 7 7 7 7 7 7 7
(3)2 0 1 6 7 9 10 10 10 10 10 10
本次填值之后,结果如下:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 1 6 7 7 7 7 7 7 7 7
(3)2 0 1 6 7 9 10 10 10 10 10 10
(5)6 0 0 0 0 0 0 0 0 0 0 0
(4)5 0 0 0 0 0 0 0 0 0 0 0
(6)4 0 0 0 0 0 0 0 0 0 0 0
... ...
后续填值过程与前一次成递归关系,最终结果如下:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 1 6 7 7 7 7 7 7 7 7
(3)2 0 1 6 7 9 10 10 10 10 10 10
(5)6 0 1 6 7 9 10 10 10 11 12 14
(4)5 0 1 6 7 9 10 10 10 11 13 14
(6)4 0 1 6 7 9 10 12 13 15 16 16
我们可以看到小偷可以偷到最贵重的价值为:16
小结:
1.一定要在纸上画,多画几遍,理清逻辑;
2.写代码时,不断调试,用计算机理解的方式(逻辑)表达出来。
具体代码如下:
小偷可以偷6样物品,重量分别为:weight[6] = {1,2,2,6,5,4},对应的价值分别为value[6] = {1,6,3,5,4,6};
小偷只背了一个最大容量为10的包;
问:小偷可以偷走的最大价值是多少?
解题思路:
1).找最贵的偷;
2).找装的最多(最轻)的偷;
3).动态规划求得最优值。
动态规划的原理就是:根据前一次的“最优值”计算当前的“最优值”。
具体步骤:
1. 用一个matrix[num][capacity+1]代表背包中一定物品、一定重量的价值。
num为特定物品,capacity为物品的重量从0到10+1(从0开始是为了便于矩阵下标0的统计)。
这个背包初始情况下为0,如下:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 0 0 0 0 0 0 0 0 0 0
(6)2 0 0 0 0 0 0 0 0 0 0 0
(3)2 0 0 0 0 0 0 0 0 0 0 0
(5)6 0 0 0 0 0 0 0 0 0 0 0
(4)5 0 0 0 0 0 0 0 0 0 0 0
(6)4 0 0 0 0 0 0 0 0 0 0 0
2. 在背包中按物品顺序依次放入,首先放入物品1,物品1对应的价值是1;
在这里,有1个逻辑:物品1在重量0<1<10的情况下,其价值都为1。
如下:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 0 0 0 0 0 0 0 0 0 0
(3)2 0 0 0 0 0 0 0 0 0 0 0
(5)6 0 0 0 0 0 0 0 0 0 0 0
(4)5 0 0 0 0 0 0 0 0 0 0 0
(6)4 0 0 0 0 0 0 0 0 0 0 0
3. 然后放入物品2;
在这里,有3个逻辑:
1).物品2在 2<2<10的情况下,其价值都为6;
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 0 6 6 6 6 6 6 6 6 6
2).在累加重量的基础上累加前一次的价值;
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 0 6 7 7 7 7 7 7 7 7
3).用前一次大的价值取代当前小的价值(补充物品1在重量1时的价值);
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 1 6 7 7 7 7 7 7 7 7
本次填值之后,结果如下:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 1 6 7 7 7 7 7 7 7 7
(3)2 0 0 0 0 0 0 0 0 0 0 0
(5)6 0 0 0 0 0 0 0 0 0 0 0
(4)5 0 0 0 0 0 0 0 0 0 0 0
(6)4 0 0 0 0 0 0 0 0 0 0 0
4. 再放入第3个物品2;
在这里,有3个逻辑:
1).物品2在 2<2<10的情况下,其价值都为3;
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 1 6 7 7 7 7 7 7 7 7
(3)2 0 0 3 3 3 3 3 3 3 3 3
2).在累加重量的基础上累加前一次的价值;
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 1 6 7 7 7 7 7 7 7 7
(3)2 0 0 3 3 9 10 10 10 10 10 10
3).用前一次大的价值取代当前小的价值;
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 1 6 7 7 7 7 7 7 7 7
(3)2 0 1 6 7 9 10 10 10 10 10 10
本次填值之后,结果如下:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 1 6 7 7 7 7 7 7 7 7
(3)2 0 1 6 7 9 10 10 10 10 10 10
(5)6 0 0 0 0 0 0 0 0 0 0 0
(4)5 0 0 0 0 0 0 0 0 0 0 0
(6)4 0 0 0 0 0 0 0 0 0 0 0
... ...
后续填值过程与前一次成递归关系,最终结果如下:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(1)1 0 1 1 1 1 1 1 1 1 1 1
(6)2 0 1 6 7 7 7 7 7 7 7 7
(3)2 0 1 6 7 9 10 10 10 10 10 10
(5)6 0 1 6 7 9 10 10 10 11 12 14
(4)5 0 1 6 7 9 10 10 10 11 13 14
(6)4 0 1 6 7 9 10 12 13 15 16 16
我们可以看到小偷可以偷到最贵重的价值为:16
小结:
1.一定要在纸上画,多画几遍,理清逻辑;
2.写代码时,不断调试,用计算机理解的方式(逻辑)表达出来。
具体代码如下:
#include<iostream> using namespace std; const int num = 6;//物品数量 const int weight[num] = {1,2,2,6,5,4};//物品的重量 const int value[num] = {1,6,3,5,4,6};//物品对应的价值 const int capacity = 10; //背包的容量 //背包中一定物品、一定重量的价值,默认全为0;num为特定物品,capacity为物品的重量从0到10+1(从0开始是为了便于矩阵下标0的统计)。 int matrix[num][capacity+1]= {0}; void knapsackProblem() { //第1个for,对应matrix的列,从第0个物品开始统计 for(int i_n = 0; i_n<num; i_n++) { //第2个for,对应matrix的行,从重量0到10开始统计 for(int j_w = 0; j_w<=capacity; j_w++) { //对于第1个物品,直接输入 if(i_n==0) { //物品1在重量0<1<10的情况下,其价值都为1;重量0默认价值为0。 if(weight[i_n]<=j_w) matrix[i_n][j_w] = value[i_n]; } else { //除第1个物品外,判断:1.当前物品的重量范围;2.前一次的“最优价值”与当前的“价值”比。 if((weight[i_n]<=j_w) || (matrix[i_n][j_w]<matrix[i_n-1][j_w])) { int supplement_w = j_w-weight[i_n]; //先判断是否根据前一次的“最优值”计算当前的“最优值”。 if(supplement_w>=0) { //当前重量价值 + 补充重量价值 matrix[i_n][j_w] = value[i_n]+matrix[i_n-1][supplement_w]; } //当当前的“价值”小于前一次的“最优价值”,被前一次取代。 if(matrix[i_n][j_w]<matrix[i_n-1][j_w]) { matrix[i_n][j_w]=matrix[i_n-1][j_w]; } } } } } } int main() { knapsackProblem(); //打印出矩阵 for(int i =0; i<num;i++) { for(int j = 0; j<=capacity; j++) { cout<<matrix[i][j]<<" "; } cout<<endl; } <span style="white-space:pre"> </span>return 1; }
相关文章推荐
- android studio应用(一):导入eclipse项目
- SQL笔记(13)_第十三章 查询里结合表
- Protobuf使用不当导致的程序内存上涨问题
- BZOJ1010 [HNOI2008] 玩具装箱toy
- 网页模仿
- VC程序移植到Linux下注意事项
- JCF框架源码分析系列-开头篇(一)
- java synchronized详解
- iOS精益求精 设计模式
- 详解Linux内核之双向循环链表
- Android NDK开发之 ARM与NEON指令说明
- 批量裁剪GIS数据(包含GDB,MDB,Shp)
- Struts2中的ModelDriven机制及其运用
- 解决div下放img标签,会出现空隙的情况
- SQL Server中Text和varchar(max)数据类型区别
- 数据结构-数组详解例子
- matlab的m程序转执行文件exe
- Sicily 1390. Surprising Strings
- asp.net C# Sql 查找用户是否存在
- hadoop入门--简单的MapReduce案例