01背包问题

01背包问题

一个旅行者有一个最多能装m公斤的背包,现在有n中物品,每件的重量分别是W1、W2、……、Wn,每件物品的价值分别为C1、C2、……、Cn, 需要将物品放入背包中,要怎么样放才能保证背包中物品的总价值最大?

算法分析

本次采用队列式分支限界法来解决01背包问题,拿到一个物品k存在两个节点:物品放入背包中或物品不放入背包中,根据约束条件舍去无效情况。当前物品k放入背包中时,获取当前最大总价值,下一个物品k+1也存在放入背包和不放入背包中两个节点。当物品k不放入背包时,上个节点的最总价值为当前节点的最总价值,下一个物品k+1仍然存在放入背包和不放入背包两个节点。对于物品k+1以此类推,最终根据不同的放入情况选择一个最优解作为可以放入背包物品的最大总价值。
  创建一个物品对象,封装重量、价值、单位重量价值三种属性。

// PackHeap.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

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


class bbnode
{
    template<class Typep,class Typew>
    friend class Knap;
private:
    bbnode* parent;
    bool LChild;
};

template<class Typep,class Typew>
class HeapNode
{
    template<class Typep, class Typew>
    friend class Knap;
public:
    operator Typep()const { return uprofit; }
private:
    Typep uprofit,//解点的价值上限
        profit;//当前解点的价值
    Typew weight;//当前重量
    int level;
    bbnode* ptr;
};

template<class Typep,class Typew>
class Knap
{
    friend int main(void);
public:
    Typep MaxKnapsack();
private:
    void AddLiveNode(Typep up, Typep cp, Typew cw, bool ch, int lev);
    Typep Bound(int t);
    priority_queue< HeapNode<Typep, Typew>> *H;
    Typep* p,//价值
        cp;//当前价值
    Typep* w,//重量
        cw,//当前重量
        c;//背包重量
    int* bestx,n;
    bbnode* E=nullptr;
};

template<class Typep,class Typew>
Typep Knap<Typep, Typew>::Bound(int t)
{
    Typew cleft =c- cw;
    Typep b = cp;
    while (t<=n&&w[t]<=cleft)
    {
        cleft -= w[t];
        b += p[t];
        t++;
    }
    if (t <= n)
        b += p[t] / w[t] * cleft;
    return b;

}

template<class Typep,class Typew>
void Knap<Typep, Typew>::AddLiveNode(Typep up, Typep cp, Typew cw, bool ch, int lev)
{
    bbnode* b = new bbnode;
    b->parent = E;
    b->LChild=ch;
    HeapNode<Typep,Typew> N;
    N.uprofit = up;
    N.level = lev;
    N.profit = cp;
    N.weight = cw;
    N.ptr = b;
    H->push(N);
}

template<class Typep,class Typew>
Typep Knap<Typep,Typew>::MaxKnapsack()
{
    H = new priority_queue<HeapNode<Typep, Typew>>;
    c = 7;
    cp = 0;
    cw = 0;
    bestx = new int[n + 1];
    memset(bestx, 0, sizeof(int) * (n + 1));
    int t = 1;
    Typep bestp=0;
    Typep up = Bound(1);
    while (t<n+1)
    {
        Typew wt = cw + w[t];
        if (wt < c)
        {
            if (cp + p[t] > bestp)
                bestp = cp + p[t];
            AddLiveNode(up, cp + p[t], wt, true, t+1);
        }
        up = Bound(t + 1);
        if(up>bestp)
            AddLiveNode(up, cp , cw, false, t+1);

        HeapNode<Typep, Typew> N;
        N = H->top();
        H->pop();
        E = N.ptr;
        cw = N.weight;
        cp = N.profit;
        up = N.uprofit;
        t = N.level;
    }
    for (int i = n; i >=1; i--)
    {
        bestx[i] = E->LChild;
        E = E->parent;
    }
    for (int i = 1; i <= n; i++)
    {
        cout<<bestx[i]<<"\t";
    }
    cout << endl;
    cout << "W" << endl;
    for (int i = 1; i <= n; i++)
    {
        cout << w[i] << "\t";
    }
    cout << endl;
    cout << "P" << endl;
    for (int i = 1; i <= n; i++)
    {
        cout << p[i] << "\t";
    }
    cout << endl;
    cout << cw << endl;
    return cp;
}

int main()
{
    int n = 4;
    int* w, * p;
    w = new int[n + 1];
    w[0] = 0, w[1] = 3, w[2] = 5, w[3] = 2, w[4] = 1;
    p = new int[n + 1];
    p[0] = 0, p[1] = 9, p[2] = 10, p[3] = 7, p[4] = 4;
    Knap<int, int> knap;
    knap.n = n;
    knap.w = w;
    knap.p = p;
    cout << knap.MaxKnapsack() << endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值