【问题标题】:C++ implementation of knapsack branch and bound背包分支定界的C++实现
【发布时间】:2012-07-16 04:19:47
【问题描述】:

我正在尝试使用分支和边界来实现这个背包问题的 C++ 实现。这个网站上有一个Java版本在这里:Implementing branch and bound for knapsack

我正在尝试让我的 C++ 版本打印出它应该打印的 90,但它没有这样做,而是打印出 5。

有谁知道问题出在哪里?

#include <queue>
#include <iostream>
using namespace std;

struct node
{
    int level;
    int profit;
    int weight;
    int bound;
};

int bound(node u, int n, int W, vector<int> pVa, vector<int> wVa)
{
    int j = 0, k = 0;
    int totweight = 0;
    int result = 0;

    if (u.weight >= W)
    {
        return 0;
    }
    else
    {
        result = u.profit;
        j = u.level + 1;
        totweight = u.weight;

        while ((j < n) && (totweight + wVa[j] <= W))
        {
            totweight = totweight + wVa[j];
            result = result + pVa[j];
            j++;
        }

        k = j;

        if (k < n)
        {
            result = result + (W - totweight) * pVa[k]/wVa[k];
        }
        return result;
    }
}

int knapsack(int n, int p[], int w[], int W)
{
    queue<node> Q;
    node u, v;
    vector<int> pV;
    vector<int> wV;
    Q.empty();

    for (int i = 0; i < n; i++)
    {
        pV.push_back(p[i]);
        wV.push_back(w[i]);
    }

    v.level = -1; 
    v.profit = 0;
    v.weight = 0;

    int maxProfit = 0;

    //v.bound = bound(v, n, W, pV, wV);
    Q.push(v);

    while (!Q.empty())
    {
        v = Q.front();
        Q.pop();

        if (v.level == -1)
        {
            u.level = 0;
        }
        else if (v.level != (n - 1))
        {
            u.level = v.level + 1;
        }

        u.weight = v.weight + w[u.level];
        u.profit = v.profit + p[u.level];

        u.bound = bound(u, n, W, pV, wV);

        if (u.weight <= W && u.profit > maxProfit)
        {
            maxProfit = u.profit;
        }

        if (u.bound > maxProfit)
        {
            Q.push(u);
        }

        u.weight = v.weight;
        u.profit = v.profit;

        u.bound = bound(u, n, W, pV, wV);

        if (u.bound > maxProfit)
        {
            Q.push(u);
        }
    }
    return maxProfit;
}

int main()
{
    int maxProfit;
    int n = 4;
    int W = 16;
    int p[4] = {2, 5, 10, 5};
    int w[4] = {40, 30, 50, 10};

    cout << knapsack(n, p, w, W) << endl;

    system("PAUSE");
}

【问题讨论】:

  • 请不要在问题解决后直接编辑。

标签: c++ knapsack-problem branch-and-bound


【解决方案1】:

我认为您将利润和权重值放入了错误的向量中。变化:

int p[4] = {2, 5, 10, 5};
int w[4] = {40, 30, 50, 10};

到:

int w[4] = {2, 5, 10, 5};
int p[4] = {40, 30, 50, 10};

你的程序会输出 90。

【讨论】:

    【解决方案2】:

    我相信您正在实施的并不是完全的分支定界算法。如果我必须将它与某些东西匹配,它更像是基于估计的回溯。

    您算法的问题在于您使用的数据结构。您正在做的只是首先推送所有第一级,然后推送所有第二级,然后将所有第三级推送到队列中,并按插入顺序将它们放回原处。你会得到你的结果,但这只是搜索整个搜索空间。

    您需要做的是始终在具有最高估计边界的节点上分支,而不是按插入顺序弹出元素。换句话说,您总是以您的方式在每个节点上分支,而不管它们的估计范围如何。分支定界技术的速度优势在于每次只在一个节点上进行分支,这最有可能导致结果(具有最高的估计值)。

    示例:在您的第一次迭代中,假设您找到了 2 个具有估计值的节点

    节点1:110

    节点2:80

    您正在将它们都推到您的队列中。您的队列变为“n2-n1-head”在第二次迭代中,您在 node1 上分支后又推送了两个节点:

    节点3:100

    node4:95

    并且您也将它们添加到队列中(“n4-n3-n2-head”。出现了错误。在下一次迭代中,您将得到 node2 但它应该是 node3 具有最高估计值。

    因此,如果我没有遗漏您的代码中的某些内容,那么您的实现和 java 实现都是错误的。您应该使用优先级队列(堆)来实现真正的分支和绑定。

    【讨论】:

      【解决方案3】:

      您将 W 设置为 16,因此结果为 5。您可以带入背包的唯一物品是物品 3,利润为 5,重量为 10。

      【讨论】:

        【解决方案4】:
                #include <bits/stdc++.h>
        using namespace std;
        
        struct Item
        {
            float weight;
            int value;
        };
        struct Node
        {
            int level, profit, bound;
            float weight;
        };
        
        bool cmp(Item a, Item b)
        {
            double r1 = (double)a.value / a.weight;
            double r2 = (double)b.value / b.weight;
            return r1 > r2;
        }
        int bound(Node u, int n, int W, Item arr[])
        {
            if (u.weight >= W)
                return 0;
            int profit_bound = u.profit;
            int j = u.level + 1;
            int totweight = u.weight;
        
            while ((j < n) && (totweight + arr[j].weight <= W))
            {
                totweight    = totweight + arr[j].weight;
                profit_bound = profit_bound + arr[j].value;
                j++;
            }
            if (j < n)
                profit_bound = profit_bound + (W - totweight) * arr[j].value /
                                                 arr[j].weight;
        
            return profit_bound;
        }
        
        int knapsack(int W, Item arr[], int n)
        {
            sort(arr, arr + n, cmp);
            queue<Node> Q;
            Node u, v;
            u.level = -1;
            u.profit = u.weight = 0;
            Q.push(u);
            int maxProfit = 0;
            while (!Q.empty())
            {
                u = Q.front();
                Q.pop();
                if (u.level == -1)
                    v.level = 0;
        
                if (u.level == n-1)
                    continue;
                v.level = u.level + 1;
                v.weight = u.weight + arr[v.level].weight;
                v.profit = u.profit + arr[v.level].value;
                if (v.weight <= W && v.profit > maxProfit)
                    maxProfit = v.profit;
                v.bound = bound(v, n, W, arr);
                if (v.bound > maxProfit)
                    Q.push(v);
                v.weight = u.weight;
                v.profit = u.profit;
                v.bound = bound(v, n, W, arr);
                if (v.bound > maxProfit)
                    Q.push(v);
            }
        
            return maxProfit;
        }
        int main()
        {
            int W = 55;   // Weight of knapsack
            Item arr[] = {{10, 60}, {20, 100}, {30, 120}};
            int n = sizeof(arr) / sizeof(arr[0]);
        
            cout << "Maximum possible profit = "
                 << knapsack(W, arr, n);
        
            return 0;
        }
        **SEE IF THIS HELPS**
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-17
          • 2011-06-10
          • 1970-01-01
          • 1970-01-01
          • 2018-10-27
          • 1970-01-01
          相关资源
          最近更新 更多