算法描述:
活结点优先队列中结点元素N的优先级由该结点的上界函数Bound计算出的值uprofit给出。
子集树中以结点N为根的子树中任一结点的价值不超过N.profit。
可用一个最大堆来实现或节点优先队列。
N.weight 是结点N所相应的重量,N.profit是N所相应的价值,N.uprofit是结点N的价值上界,最大堆以这个值作为优先级。
代码语言:javascript复制class Object{
friend int Knapsack(int *,int *,int ,int ,int *);
public:
int operator <= (Object a) const
{
return (d >= a.d);
}
private:
int ID;
float d;
};
template <class Typew,class Typep>
class Knap;
class bbnode{
friend Knap<int,int>;
friend int Knapsack(int *,int *,int,int,int *);
private:
bbnode * parent;
bool LChild;
};
template <class Typew,class Typep>
class HeapNode{
friend Knap<Typew,Typep>;
public:
operator Typep() const
{
return uprofit;
}
private:
Typep uprofit,//结点价值上界
profit;
Typew weight;
int level;//活结点所相应的重量
bbnode * ptr;
};
上界计算函数:
代码语言:javascript复制template <class Typew,class Typep>
class Knap<Typew,Typep>::Bound(int i)
{
Typew cleft = c- cw;//剩余容量
Typep b = cp;//价值上界
//以物品单位重量价值递减序装填剩余容量
while(i<=n && w[i] <= cleft)
{
cleft -= w[i];
b = p[i];
i ;
}
//装填剩余容量装满背包
if(i<=n)
b = p[i]/w[i] * cleft;
return b;
}
分支限界搜索函数:
代码语言:javascript复制template <class Typew,class Typep>
Typep Knap<Typew,Typep>::MaxKnapsack()
{
//优先队列式分支限界法,返回最大价值,bestx返回最优解
//定义最大堆的容量为1000
H = new MaxHeap< HeapNode<Typew,Typep> >(1000);
//为bestx分配存储空间
bestx = new int [n 1];
//初始化
int i=1;
E= 0;
cw = cp = 0;
Typep bestp = 0;
Typep up = Bound(1);
//搜索子集空间树
while(i!=n 1)//非叶节点
{
//检查当前扩展结点的左儿子结点
Typew wt = cw w[i];
if(wt <= c)
{
if(cp p[i] > bestp)
bestp = cp p[i];
AddLiveNode(up,cp p[i],cw w[i],true,i 1);
}
up = Bound(i 1);
//检查扩展结点的右儿子结点
if(up >= bestp)//右子树 可能含有最优解
AddLiveNode(up,cp,cw,false,i 1);
//取得下一扩展点
HeapNode<Typep,Typew> N;
H->DeleteMax(N);
E = N.ptr;
cw = N.weight;
cp = N.profit;
up = N.uprofit;
i = N.level;
}
//构造当前最优解
for(int j=n;j>0;j--)
{
bestx[j] = E->LChild;
E = E->parent;
}
return cp;
}
主要程序代码:
测试中.....(暂时不好使)
代码语言:javascript复制#include <iostream>
#include <algorithm>
class Object{
friend int Knapsack(int *,int *,int ,int ,int *);
public:
int operator <= (Object a) const
{
return (d >= a.d);
}
private:
int ID;
float d;
};
template <class Typew,class Typep>
class Knap;
class bbnode{
friend Knap<int,int>;
friend int Knapsack(int *,int *,int,int,int *);
private:
bbnode * parent;
bool LChild;
};
template <class Typew,class Typep>
class HeapNode{
friend Knap<Typew,Typep>;
public:
operator Typep() const
{
return uprofit;
}
private:
Typep uprofit,//结点价值上界
profit;
Typew weight;
int level;//活结点所相应的重量
bbnode * ptr;
};
template <class Typew,class Typep>
class Knap{
friend Typep Knapsack(Typep *,Typew *,Typew ,int ,int *);
public:
Typep MaxKnapsack();
private:
MaxHeap<HeapNode<Typep,Typew> > * H;
Typep Bound(int i);
void AddLiveNode(Typep up,Typep cp,Typew cw,bool ch,int level);
bbnode * E;
Typew c;
int n;
Typew * w;
Typep *p;
Typew cw;
Typep cp;
int *bestx;
};
template <class Typew,class Typep>
class Knap<Typew,Typep>::Bound(int i)
{
Typew cleft = c- cw;//剩余容量
Typep b = cp;//价值上界
//以物品单位重量价值递减序装填剩余容量
while(i<=n && w[i] <= cleft)
{
cleft -= w[i];
b = p[i];
i ;
}
//装填剩余容量装满背包
if(i<=n)
b = p[i]/w[i] * cleft;
return b;
}
template <class Typep,class Typew>
void Knap<Typep,Typew>::AddLiveNode(Typep up,Typep cp,Typew cw,bool ch,int lev)
{
//将一个新的活结点插入到子集树 和 最大堆 H中
bbnode *b = new bbnode;
b->parent = E;
b->LChild = ch;
HeapNode<Typep,Typew> N;
N.uprofit = up;
N.profit = cp;
N.weight = cw;
N.level = lev;
N.ptr = b;
H->Insert(N);
}
template <class Typew,class Typep>
Typep Knap<Typew,Typep>::MaxKnapsack()
{
//优先队列式分支限界法,返回最大价值,bestx返回最优解
//定义最大堆的容量为1000
H = new MaxHeap< HeapNode<Typew,Typep> >(1000);
//为bestx分配存储空间
bestx = new int [n 1];
//初始化
int i=1;
E= 0;
cw = cp = 0;
Typep bestp = 0;
Typep up = Bound(1);
//搜索子集空间树
while(i!=n 1)//非叶节点
{
//检查当前扩展结点的左儿子结点
Typew wt = cw w[i];
if(wt <= c)
{
if(cp p[i] > bestp)
bestp = cp p[i];
AddLiveNode(up,cp p[i],cw w[i],true,i 1);
}
up = Bound(i 1);
//检查扩展结点的右儿子结点
if(up >= bestp)//右子树 可能含有最优解
AddLiveNode(up,cp,cw,false,i 1);
//取得下一扩展点
HeapNode<Typep,Typew> N;
H->DeleteMax(N);
E = N.ptr;
cw = N.weight;
cp = N.profit;
up = N.uprofit;
i = N.level;
}
//构造当前最优解
for(int j=n;j>0;j--)
{
bestx[j] = E->LChild;
E = E->parent;
}
return cp;
}
template <class Typew,class Typep>
Typep Knapsack(Typep p[],Typew w[],Typew c,int n,int bestx[])
{
Typew W = 0;
Typep P = 0;
//按 单位重量价值 排序
Object * Q = new Object [n];
for(int i=1;i<=n;i )
{
Q[i-1].ID = i;
Q[i-1].d = 1.0*p[i]/w[i];
P = p[i];
W = w[i];
}
if(W<=c)
return P;
Sort(Q,n);
Knap<Typew,Typep> K;
K.p = new Typep[n 1];
K.w = new Typew[n 1];
for(int i=1;i<=n;i )
{
K.p[i] = p[Q[i-1].ID];
K.w[i] = p[Q[i-1].ID];
}
K.cp = 0;
K.cw = 0;
K.c = c;
K.n = n;
Typep bestp = K.MaxKnapsack();
for(int j=1;j<=n;j )
{
bestx[Q[i-1].ID] = K.bestx[j];
cout<<bestx[Q[i-1.ID]]<<endl;
}
delete [] Q;
delete [] K.w;
delete [] K.p;
delete [] K.bestx;
cout<<"最大价值为"<<bestp<<endl;
return bestp;
}
int main()
{
int n,m;
int w[100],p[100],best[100];
cout<<"请输入想要输入的物品个数 及 背包重量:"<<endl;
cin>>n>>m;
cout<<"请依次输入想要输入的物品重量 及 价值"<<endl;
for(int i=0;i<n;i )
cin>>w[i]>>p[i];
Knapsack(w,p,m,n,best);
return 0;
}