0-1背包问题的回朔法实现
设有0-1背包问题,p(1,2...n)价值,w(1,2...n) 重,c背包容量。
利用深度优先搜索,构造解空间树。每一个物品有1(取),0(不取),分别对应解空间树的左右子树。故解空间树为n+1深的完全二叉树。每个节点表示当前总价值。
算法实现:以类的方式,以减少参数的传递。n(物品数),bestp最大价值,cp 当前价值。
#include <iostream>
#include <stdio.h>
using namespace std;
class knapack
{
friend int knap();
public:
int n;//物品数量
int *p;//物品价值
int *w;//物品重量
int c;//背包容量
int bestp;
int cp;
int cw;//当前重量
int *bestl;//最优路径
int *cl;//当前路径
public:
void backtrack(int i);
int bound(int i);//计算上界,若上界小于bestp,剪枝
};
void knapack:: backtrack(int i)//i深度
{
if(i>n)
{
bestp=cp;
bestl=cl;
return;
}
if(cw+w[i]<=c)
{
//进入左子树
cw+=w[i];
cl[i]=1;
cp+=p[i];
backtrack(i+1);
cw-=w[i];
cl[i]=0;
cp-=p[i];
}
if(bound(i+1)>bestp)
{
//进入又子树
backtrack(i+1);
}
}
int knapack::bound(int i)
{
//计算上界
int b=cp;
int leflc=c-cw;
for(int j=i;i<=n && w[i] <leflc;i++)
{
b+=p[i];
leflc-=w[i];
}
if (i<=n)
b+=p[i]*leflc/w[i];
return b;
}
int knap(int n,int w[],int p[],int c)
{
class knapack a;
a.n=n;
a.c=c;
a.p=p;
a.w=w;
a.bestl=new int [n];
a.cl=new int [n];
a.bestp=0;
a.cp=0;
a.cw=0;
a.backtrack(1);
return a.bestp;
}
int main(int argc, char const *argv[])
{
int n;
cin>>n;
int *p=new int [n+1];
int *w=new int [n+1];
for (int i = 1; i <= n; ++i)
{
cin>>w[i];
}
for (int i = 1; i <= n; ++i)
{
cin>>p[i];
}
int c;
cin>>c;
printf("%d\n",knap(n,w,p,c));
return 0;
}