背包问题--动态规划

问题的提出

背包问题(Knapsack problem)是一种组合优化的NP完全问题。
问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,
在限定的总重量内,我们如何选择,才能使得物品的总价格最高。

问题解决

本文介绍使用动态规划的方法解决此问题
算法思想:

  • 1.将原问题分解为子问题:原问题为求解最大价值,分解为背包载重容量从1到最大量c分别能装多少价值东西的 若干问题
  • 2.确定状态:使用 sum_value_matrix[n][c]保存,n表示前n个物件(number),c表达背包容量(capacity),所以这个变量意义为背包容量为c,前n个物件能装入的最大价值
  • 3.确定初始态值:当容量为1时,因为所有物品重量都大于1,所以sum_value_matrix[n][1]={0,0,0,0,0}
  • 4.确定状态转移方程:sum_value_matrix[n][c]=max(sum_value_matrix[n-1][c], sum_value_matrix[n-1][c-w[n]]+v[n])
    w[i]表示第i个物件的重量(weight),v[n]表示第一个物件的价值(value)
    方程意义:
    考虑第n件物品 放1 或者 不放0 时,
    如果不放,那么其价值为前面 n-1 物品价值 sum_value_matrix[n-1][c]
    如果放,那么其价值为前面 n-1 物品在容量为 c-w[n] 的时候的价值sum_value_matrix[n-1][c-w[n]],
    加上第n件物品的价值 v[n](理由:满足“最优化原理”)

代码:

C++代码

class PackageSolver {
public:
    int sum_value_matrix[6][11];

    int knapsack(PackageItem*  items) {
        init(items);
        for (int c = 2; c <= 10; c++) {
            for (int n = 2; n <= 5; n++) {
                if (c < items[n].weight) {
                    //背包capacity 比第n项小
                    sum_value_matrix[n][c] = sum_value_matrix[n - 1][c];
                }
                else {
                    //装得下第n项
                    //undo: c - items[n].weight>0?  else?
                    int temp1 = sum_value_matrix[n - 1][c];
                    int temp2 = items[n].value;

                    if (c - items[n].weight > 0) {
                        temp2 = sum_value_matrix[n - 1][c - items[n].weight] + items[n].value;
                    }
                    sum_value_matrix[n][c] = temp1 > temp2 ? temp1 : temp2;
                }
            }
        }
        return sum_value_matrix[5][10];
    }

    //初始化
    void init(PackageItem*  items) {
        //初始化0
        for (int n = 1; n <= 5; n++) {
            for (int c = 1; c <= 10; c++) {
                sum_value_matrix[n][c] = 0;
            }
        }
        //初始化第一列,第n件物品的weight value
        for (int n = 1; n <= 5; n++) {
            sum_value_matrix[n][1] = 0;
        }
        //初始化第一行,只装第一个物品 容量为c时候的 总value
        for (int c = 1; c <= 10; c++) {
            if (c >= items[1].value) {
                sum_value_matrix[1][c] = items[1].value;
            }
            //cout << sum_value_matrix[1][c];
        }
    }
    void print() {
        cout<<"x:capacity   y:top n items"<<endl;
        for (int n = 1; n <= 5; n++) {
            for (int c = 1; c <= 10; c++) {
                    cout << sum_value_matrix[n][c] << ends;
            }
            cout << endl;
        }
        cout << endl;
    }
};

背包项

struct PackageItem
{
    string name;
    int weight;
    int value;

    PackageItem(string name, int weight, int value) {
        this->name = name;
        this->weight = weight;
        this->value = value;
    }
    void print() {
        cout << "name:" << name << ends
             << "weight:" << weight << ends
             << "value:" << value << endl;
    }
};

测试代码

class Problem2Tester {
public:
    //为了使得下标与实际意义一致,所以设置item[0]为空
    struct PackageItem items[6] = {
        { " ", 0, 0 },
        { "a", 2, 2 },
        { "b", 2, 3 },
        { "c", 6, 5 },
        { "d", 5, 4 },
        { "e", 4, 6 },
    };
    PackageSolver ps;

    void item_test() {
        for (int i = 0; i <= 5; i++) {
            items[i].print();
        }
    }
    void init_test() {
        ps.print();
        ps.init(items);
        ps.print();
    }
    void knapsack_test() {
        ps.init(items);
        ps.print();
        ps.knapsack(items);
        ps.print();
    }
}tester2;

参考:
http://blog.csdn.net/mu399/article/details/7722810
http://blog.sina.com.cn/s/blog_6dcd26b301013810.html

原文地址:https://www.cnblogs.com/liyuquan/p/7082235.html