求解0—1背包问题的优先队列式分支限界算法

#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;

#define NUM 100
class object
{
	friend int knapsack(int *,int *,int ,int);
public:
	int operator < (object a)const
	{
		return (ratio>a.ratio);
	}
private:
	int ID;
	double ratio;
};

class node
{
	friend class knap;
	friend int knapsack(int *,int *,int ,int);
private:
	node *parent;
	bool lchild;
};

class queueNode
{
	friend class knap;
public:
	friend bool operator < (queueNode a,queueNode b)
	{
		if(a.uprofit<b.uprofit) return true;
		else return false;
	}
private:
	int uprofit;
	int profit;
	int weight;
	int level;
	node *ptr;
};

class knap
{
	friend int knapsack(int *,int *,int ,int);
public:
	int maxKnapsack();
private:
	priority_queue <queueNode> H;
	int bound(int i);
	void addLiveNode(int up,int cp,int cw,bool ch,int level);
	node *E;
	int c;
	int n;
	int w[NUM];
	int p[NUM];
	int cw;
	int cp;
	int bestx[NUM];
};

int knap::bound(int i)
{
	int cleft = c-cw;
	int b = cp;
	while(i<=n&&w[i]<=cleft)
	{
		cleft -= w[i];
		b += p[i];
		i++;
	}
	if(i<=n) b += 1.0*cleft*p[i]/w[i];
	return b;
}

void knap::addLiveNode(int up,int cp,int cw,bool ch,int lev)
{
	node *b = new node;
	b->parent = E;
	b->lchild = ch;
	queueNode N;
	N.uprofit = up;
	N.profit = cp;
	N.weight = cw;
	N.level = lev;
	N.ptr = b;
	H.push(N);
}

int knap::maxKnapsack()
{	
	int i = 1;
	E = 0;
	cw = cp = 0;
	int bestp = 0;
	int up = bound(1);
	while(i!=n+1)
	{
		int 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);
		queueNode N;
		N = H.top();
		H.pop();
		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;
}

int knapsack(int p[],int w[],int c,int n)
{
	int i;
	int bestx[NUM];
	object *Q = new object[n];
	for(i=0; i<n; i++)
	{
		Q[i].ID = i+1;
		Q[i].ratio = 1.0*p[i]/w[i];
	}
	stable_sort(Q,Q+n);
	knap K;
	for(i=1; i<=n; i++)
	{
		K.p[i] = p[Q[i-1].ID-1];
		K.w[i] = w[Q[i-1].ID-1];
	}
	K.cp = 0;
	K.cw = 0;
	K.c = c;
	K.n = n;
	int bestp = K.maxKnapsack();
	for(i=1; i<=n; i++)
		bestx[Q[i-1].ID] = K.bestx[i];
	for(i=1; i<=n; i++)
		if(bestx[i]==1) printf("%d ", i);
	printf("\n");
	delete [] Q;
	return bestp;
}

int main()
{	
	int w[NUM];
	int p[NUM];
	int c;
	int n;
	while(scanf("%d%d",&c, &n)!=EOF)
	{
		//printf("%d %d\n",c,n);
		for(int i=0; i<n; i++)
			scanf("%d%d",&w[i],&p[i]);
		printf("%d\n", knapsack(p,w,c,n));
	}
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值