分支限界法求解01背包问题

使用优先队列,求最大价值
首先按照性价比排序
bound函数表示当前状态之后的选择都是理想的,这样能到达的理想最大值
每个节点存储物品在树中的层次,表示已经对多少个物品做出了选择,当前状态放入背包的总价值和重量。

#include <bits/stdc++.h>
using namespace std;

const int N = 110;
struct stone{
	int v, w;
	stone(){
		v =  w = 0;
	}
	bool operator < (stone b) const {
		return v/w > b.v/b.w;
	}
}item[N];

struct node{
	int level, cv, cw;
	float bound;
	bool operator< (const node& b) const{
		return bound > b.bound;
	}
};

int best, W, n;
inline void Initialize(priority_queue<node> &Q){
	while(Q.size()) Q.pop();
}

float bound(node& p){
	int left = W-p.cw;
	float val = p.cv;
	int i;
	
	for(i = p.level; i <= n && item[i].w <= left; i++){
		left -= item[i].w;
		val += item[i].v;
	}
	if(i <= n) val += item[i].v*1.0/item[i].w*left;
	return val;
}
priority_queue<node> PQ;
void knapsack(){
	node u, v;
	Initialize(PQ);
	v = {0,0,0,0};
	best = 0;
	v.bound = bound(v);
	PQ.push(v);
	while(PQ.size()){
		v = PQ.top();
		PQ.pop();
		if(v.level == n) continue;
		if(v.bound > best){
			u.level = v.level+1;
			u.cw = v.cw+item[u.level].w;
			u.cv = v.cv+item[u.level].v;
			//printf("%d %d\n", u.cw, u.cv);
			if(u.cw <= W && u.cv > best)
				best = u.cv;
			u.bound = bound(u);
			if(u.bound > best) PQ.push(u);
			u.cw = v.cw; u.cv = v.cv;
			u.level = v.level+1;
			u.bound = bound(u);
			if(u.bound > best) PQ.push(u);
		}
	}
}
int main(){
	scanf("%d%d", &n, &W);
	for(int i = 1; i <= n; i++) scanf("%d", &item[i].w);
	for(int i = 1; i <= n; i++) scanf("%d", &item[i].v);
	sort(item+1, item+1+n);
	knapsack();
	printf("%d\n", best);
	return 0;
}
/*
4 7
3 5 2 1
9 10 7 4

20
*/
  • 7
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值