01背包问题——分支限界法

#include
using namespace std;
int n,w;//物品数量和最大容量 
int best;//记录最优值 
int bestx[1000];//记录最优解 
struct knap{//物品 
	int weight;//重量 
	int value;//价值 
	int m;//物品的序号 
}k[1000];
struct Node{//节点 
	int level;//层数,也代表了第几个物品
	int cv;//当前价值
	int cw;//当前容量
	double bound;//最大上界,用于排序 
	int cp[1000];//当前解
	friend bool operator< (Node x, Node y)//优先队列用上界函数排序
    {
        return x.bound < y.bound;
    }
}*p;
bool cmp(knap x,knap y){ //物品性价比排序 
    return 1.0*x.value/x.weight>1.0*y.value/y.weight;   //定义降序排序(从大到小) 
}
//struct cmp1{
//	bool operator()(Node* p1,Node* p2)
//		return p1->boundbound; 
//}; 
priority_queue<Node>a;//定义优先队列,队列中存放的是节点
double Bound(int t,int cw,int cv){//贪心法将背包装满计算上界函数
	int cleft=w-cw;
	int b=cv;
	while(t<=n&&k[t].weight<=cleft)
	{
		cleft-=k[t].weight;
		b+=k[t].value;
		t++;
	}
	if(t<=n)
		b+=1.0*k[t].value/k[t].weight*cleft;
	return b;
}
void knapsack(){
	Node n1;//上层节点 
	Node n2;//存放两个可能的扩展节点               
	n1.cv=k[0].value;//根节点 
	n1.cw=k[0].weight;
	n1.level=0;
	n1.bound=Bound(1,n1.cw,n1.cv);//根节点入队列 
	a.push(n1); 
	while(a.size())//队列不空 
	{
		n1=a.top();//上层节点出队列 
		a.pop();
		if(n1.level==n)//到达叶子节点
		{
			if(n1.cv>best)//如果结果更好 
			{
				best=n1.cv;//更新最优值 
				//bestx=n1.cp;
				memcpy(bestx,n1.cp,sizeof(n1.cp));//更新最优解,memcpy将中间的后面个字符赋给前面 
//				for(int i=1;i<=n1.level;i++)
//					bestx[i]=n1.cp[i];
			} 
			continue; //跳过本次循环 
		} 
		//没到达叶子节点,开始扩展节点
		n2.level=n1.level+1;//层数+1
//		for(int i=1;i<=n1.level;i++)
//			n2.cp[i]=n1.cp[i];
		memcpy(n2.cp,n1.cp,sizeof(n1.cp));//将当前的解存入 
		//层数和当前的解对放与不放是通用的 
		//1,当前物品放入背包,这种情况要考虑剪枝 
		if(n1.cw+k[n2.level].weight<w)//层数其实也代表了第几个物品 
		{
			n2.cw = n1.cw+k[n2.level].weight; 
			n2.cv = n1.cv+k[n2.level].value;
			n2.bound=Bound(n2.level,n2.cw,n2.cv);//重新计算限界函数 
			
			n2.cp[n2.level]=1;//1代表该物品放入了 
			if(n2.bound>best)
				a.push(n2);
		}
		//0,当前物品没放入背包 
		n2.cw=n1.cw;//因为n2的一系列值需要更新为不放的之后在入队列 
		n2.cv=n1.cv;
		n2.bound=Bound(n2.level,n2.cw,n2.cv);
		n2.cp[n2.level]=0;//0代表该物品没放
		if(n2.bound>best)
			a.push(n2);
	}
}
int main()
{
	cin>>n>>w;
	for(int i=1;i<=n;i++)
		cin>>k[i].weight>>k[i].value;
	sort(k,k+n,cmp);//对物品进行性价比排序 
	knapsack();
	cout<<best<<endl;
	for(int i=1;i<=n;i++)
		cout<<bestx[i]<<" ";
	return 0;
 } 

你可能感兴趣的:(算法,c++,c语言,广度搜索)