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;
}