揹包問題--動態規劃

問題的提出

揹包問題(Knapsack problem)是一種組合優化的NP徹底問題。
問題能夠描述爲:給定一組物品,每種物品都有本身的重量和價格,
在限定的總重量內,咱們如何選擇,才能使得物品的總價格最高。html

問題解決

本文介紹使用動態規劃的方法解決此問題
算法思想:c++

  • 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測試

相關文章
相關標籤/搜索