【问题标题】:Printing Knapsack items (Repetition of items allowed)打印背包物品(允许重复物品)
【发布时间】:2019-09-08 10:53:35
【问题描述】:

我实现了 2 种解决背包问题的方法,但我无法以一种方式打印选定的项目,而另一种则不能很好地工作,因为它错过了我的第一个项目值。 Baiscally,我的背包问题是将一个长度为 N 的条划分为长度为 1,2,....,N 的子条,其中每个子条具有不同的成本。

当然,只要不超过长度,就可以重复项目。 所以: 1)我有一个长度为 N 的条,可以分割。从 1 到 N 的每个部分都有一个价格相关。 2)背包找到最大利润,可以多次拿相同的物品。 3)打印背包选择的元素。

我的问题是: 1)在第一段代码中,我无法理解如何打印所选项目。 2)我尝试了矩阵方法,但我不明白如何设置允许重复项目的背包矩阵方程。

这是我的第一次尝试,这确实有效并给了我正确的答案,但我无法真正理解如何打印所选项目。

int *k = malloc(sizeof(int ) * lenght+1);
for( i = 0 ; i <= lenght; i++) k[i] = 0;

填充背包数组。

for(i = 0 ; i <= lenght ; i++){
    for(w = 0 ; w < lenght ; w++){
        if( bar[w] <= i){
            k[i] = searchmax( prices[w] + k[i-bar[w]] , k[i] );
        } 
    }
}

这是我的第二种方法,它不起作用,但我更清楚如何打印之后的项目,因为它适用于经典背包。

int **k = malloc(sizeof(int*) * (lenght+1));
for(i=0;i<=lenght;i++) k[i] = malloc(sizeof(int)*(lenght+1));

for( i = 0 ; i <= lenght; i++)k[0][i]= 0;
for(i = 0 ; i <=lenght;i++) k[i][0]=0;

for(i=1;i<=lenght;i++){
    for(w=1;w<=lenght;w++){
        if(bar[i]<=w){
            printf("\nPrices: %d  Barlenght: %d" , prices[i], bar[i]);
            k[i][w]=searchmax(prices[i]+k[i][w-bar[i]], k[i-1][w]);
        }
        else k[i][w] = k[i-1][w];

    }
}

这组输入的结果:柱的长度:4

长度为 1 到 N 的子条的价格(在这种情况下 N 为 4)为:1、5、8、9。

应该是:利润:10,物品:2,2

【问题讨论】:

    标签: c algorithm knapsack-problem


    【解决方案1】:

    仅当元素“保存在背包中”时才应打印该元素。在每次迭代中,您都会检查是将元素放入背包还是丢弃它。在您的代码中,您应该检查这一点:如果一个元素“保存在背包中”,请打印它及其重量,以及已经在背包中的其他值,并且在添加此元素时不超过容量背包。有几种方法可以做到这一点。我想到了这个:在执行该方法时,将所选值保存在背包中,为它的每个可能容量(如果它有容量 W,则必须将所选值存储在一个矩阵中,其中每一行 w表示一个值 0

    代码

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <stdexcept>
    #include <string>
    
    
    /**
    * Responsible for dealing with the unbounded knapsack problem.
    */
    class UnboundedKnapsack
    {
        //-------------------------------------------------------------------------
        //      Attributes
        //-------------------------------------------------------------------------
        /**
        * Stores maximum value of the knapsack for a certain capacity.
        */
        std::vector<int> knapsack;
    
        /**
        * Stores elements that are part of the knapsack with a certain capacity.
        * <li><b>Line:</b> Knapsack capacity</li>
        * <li><b>Column:</b> Elements</li>
        */
        std::vector<std::vector<int> > selectedElements;
    
        /**
        * Stores maximum knapsack capacity.
        */
        int maximumCapacity;
    
    
    public:
        //-------------------------------------------------------------------------
        //      Constructor
        //-------------------------------------------------------------------------
        UnboundedKnapsack()
        {
            maximumCapacity = -1;
        }
    
    
        //-------------------------------------------------------------------------
        //      Destructor
        //-------------------------------------------------------------------------
        ~UnboundedKnapsack()
        {
            delete this;
        }
    
    
        //-------------------------------------------------------------------------
        //      Methods
        //-------------------------------------------------------------------------
        /**
        * Unbounded knapsack allows to use one or more occurrences of an item.
        *
        * @param        w Weight of the elements
        * @param        v Value of the elements
        * @param        N Number of itens
        * @param        W Maximum weight capacity
        * @return       This object to allow chained calls
        */
        UnboundedKnapsack* knapsack_unbounded(std::vector<int>& w, std::vector<int>& v, int N, int W)
        {
            // Stores the maximum value which can be reached with a certain capacity
            knapsack.clear();
            knapsack.resize(W + 1);
    
            maximumCapacity = W + 1;
    
            // Stores selected elements with a certain capacity
            selectedElements.resize(W + 1);
    
            // Initializes maximum value vector with zero
            for (int i = 0; i < W + 1; i++) {
                knapsack[i] = 0;
            }
    
            // Computes the maximum value that can be reached for each capacity
            for (int capacity = 0; capacity < W + 1; capacity++) {
                // Goes through all the elements
                for (int n = 0; n < N; n++) {
                    if (w[n] <= capacity) {
                        // max(knapsack[capacity], knapsack[capacity - w[n]] + v[n])
                        if (knapsack[capacity] <= knapsack[capacity - w[n]] + v[n]) {
                            knapsack[capacity] = knapsack[capacity - w[n]] + v[n];
    
                            // Stores selected elements
                            selectedElements[capacity].clear();
                            selectedElements[capacity].push_back(n + 1);
    
                            for (int elem : selectedElements[capacity - w[n]]) {
                                selectedElements[capacity].push_back(elem);
                            }
                        }
                    }
                }
            }
    
            return this;
        }
    
        /**
        * Returns maximum value for a certain number of elements and a certain
        * capacity.
        *
        * @param        capacity Capacity of the knapsack
        * @return       Maximum possible value with capacity provided
        * @throws       std::invalid_argument If capacity provided is out of bounds
        */
        int getMaximumValue(int capacity)
        {
            if (capacity < 0 || capacity >= maximumCapacity)
                throw std::invalid_argument("Capacity out of bounds");
    
            return knapsack[capacity];
        }
    
        /**
        * Returns elements that belong to the knapsack with a certain capacity.
        *
        * @param        capacity Capacity of the knapsack
        * @return       Elements that are part of the knapsack with the capacity
        * provided
        * @throws       std::invalid_argument If capacity provided is out of bounds
        * @apiNote      Elements are referenced by their index + 1
        */
        std::vector<int>& getSelectedElements(int capacity)
        {
            if (capacity < 0 || capacity >= maximumCapacity)
                throw std::invalid_argument("Capacity out of bounds");
    
            return selectedElements[capacity];
        }
    
        /**
        * Returns elements that are part of the knapsack with a certain capacity.
        * This method will return a {@link std::string} with the following format:
        * <code>[elem1, elem2, elem3...]</code>
        *
        * @param        capacity Capacity of the knapsack
        * @return       Elements that are part of the knapsack with the capacity
        * provided
        * @apiNote      Elements are referenced by their index + 1
        */
        std::string selectedElements_toString(int capacity)
        {
            std::string response = "[";
    
            for (int element : selectedElements[capacity]) {
                response.append(std::to_string(element));
                response.append(", ");
            }
    
            // Removes last ", "
            response.pop_back();
            response.pop_back();
    
            response.append("]");
    
            return response;
        }
    };
    
    
    //-------------------------------------------------------------------------
    //      Main
    //-------------------------------------------------------------------------
    /**
    * Example made based on this exercise:
    * {@link https://www.urionlinejudge.com.br/repository/UOJ_1487_en.html}
    */
    int main()
    {
        UnboundedKnapsack* knapsack = new UnboundedKnapsack();
        int totalCapacity = 60, elements = 5;
        std::vector<int> elements_weight = { 10, 20, 5, 50, 22 };
        std::vector<int> elements_values = { 30, 32, 4, 90, 45 };
    
        knapsack->knapsack_unbounded(elements_weight, elements_values, elements, totalCapacity);
    
        std::cout << "Maximum value: "
            << knapsack->getMaximumValue(totalCapacity)
            << std::endl;
        std::cout << "Selected elements: "
            << knapsack->selectedElements_toString(totalCapacity)
            << std::endl;
    
        system("pause");
    
        return 0;
    }
    

    输出

    Maximum value: 180
    Selected elements: [1, 1, 1, 1, 1, 1]
    

    我希望这会有所帮助。如果您有兴趣,我还实现了一个版本,显示与经典版本的背包一起存储的元素。可在此处获得: https://github.com/williamniemiec/algorithms/blob/master/Dynamic%20programming/knapsack/c%2B%2B/BoundedKnapsack.cpp

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-16
      • 2016-11-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多