zoukankan      html  css  js  c++  java
  • 背包问题--动态规划

    问题的提出

    背包问题(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

  • 相关阅读:
    【网络流24题】方格取数问题(最大流)
    运维之思科篇——NAT基础配置
    NAT地址转换常用命令详解
    NAT(地址转换技术)详解
    Linux命令之grep用法详解:grep与正则表达式 [转]
    curl查询公网出口IP
    CentOS下安装Telnet服务
    Linux之Xinetd服务介绍
    上市公司年报发布时间是什么时候?
    jackson序列化字段字母大小写及字段名重复
  • 原文地址:https://www.cnblogs.com/liyuquan/p/7082235.html
Copyright © 2011-2022 走看看