1、算法描述
0-1背包问题时子集选取问题。0-1背包问题的解空间可用子集树表示。集0-1背包问题的回溯法与装载问题的回溯法十分相似。在搜索解空间树时,只要其左儿子结点是一个可行结点,搜索就进入其左子树。当右子树中可能包含最优解时才进入右子树搜索。否则将右子树剪去。设r是当前剩余物品价值总和;cp是当前价值,bestp是当前最优价值。当cp+r<<bestp时,可剪去右子树。计算右子树中解的上界的更好方法是将剩余物品依其单位价值排序,然后依次装入物品,直至装不下时,再装入该物品的一部分而装满背包。由此得到的价值是右子树中解的上界。
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
template <class Typew,class Typep>
class Knap {
public :
Typep Bound(int i);
void Backtrack(int i);
Typew c; //背包容量
int n; //物品数
int *bestx; //记录当前最优装载
Typew *w; //物品重量数组
Typep *p; //物品价值数组
Typep cp; //当前价值
Typew cw; //当前重量
Typep bestp; //当前最优价值
};
template<class Typew,class Typep>
void Knap<Typew,Typep>::Backtrack(int i)
{
if(i>n) {//达到叶子节点
bestp=cp;
for(int j=1;j<=n;j++)
printf("%d ",bestx[j]);
printf("\n");
return ;
}
if(cw+w[i]<=c) //进入左子树
{
bestx[i]=1;
cw+=w[i];
cp+=p[i];
Backtrack(i+1);
cw-=w[i];
cp-=p[i];
}
if(Bound(i+1)>bestp)//进入右子树
{
Backtrack(i+1);
bestx[i]=0;
}
}
template<class Typew,class Typep>
Typep 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]*cleft/w[i];
return b;
}
class Object{
friend int Knapspack(int *,int *,int ,int);
public :
int operator<=(Object a)const
{
return (d>=a.d);
}
public:
int ID;
float d;
};
bool cmp(Object A,Object B)
{
if(B.d<=A.d)
return true;
else
return false;
}
template<class Typew,class Typep>
Typep Knapstack(Typep p[],Typew w[],Typew c,int n)
{
//为Knap::Backtrack初始化
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,Q+n,cmp);
// for(int j=1;j<=n;j++)
// printf("%f ",Q[j-1].d);
Knap<Typew,Typep> K;
K.bestx = new int[n+1];
for(int j=0;j<=n;j++)
K.bestx[j]=0;
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]=w[Q[i-1].ID];
}
K.cp = 0;
K.cw = 0;
K.c = c;
K.n = n;
K.bestp = 0;
//回溯搜索
K.Backtrack(1);
delete[] Q;
delete[] K.w;
delete[] K.p;
return K.bestp;
}
void main()
{
int p[]={0,9,10,7,4};
int w[]={0,3,5,2,1};
int n=4;
int c=7;
int sum;
sum=Knapstack(p,w,c,n);
printf("%d \n",sum);
system("pause");
}