背包问题

来源:互联网 发布:淘宝违禁品有哪些 编辑:程序博客网 时间:2024/05/21 20:28
有一个小偷,跑到一户人家去偷东西;
小偷可以偷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;}


0 0
原创粉丝点击