您当前的位置: 首页 > 

超大背包问题(二进制枚举 + 二分)

发布时间:2020-11-30 20:47:00 ,浏览量:5

超大背包问题
第一次看到这一题好像是在某一场比赛,就是给你一个炸空间和时间的背包,让你选最大的价值,看似是01背包 然鹅今天在挑战程序设计这本书上看到了这题,看到了作者的做法,感觉豁然开朗,直接暴搜也会炸,但是我们 可以把这些物品拆分成两堆,然后我们用二进制枚举两个堆的物品,时间复杂度为\(O(n*2^{(n/2)})\) 在枚举第二堆的时候我们就可以在第一个堆里通过二分搜索找到满足条件物品堆,然后选择最优的结果就行 每次二分查询时间log(m),m表示的是第一堆物品有效个数,具体请看代码讲解
#include#include#includeusing namespace std;

const int N = 45;
typedef long long ll;
ll w[N],v[N],W;
int n;

struct Node {
	ll w,v;
}ps[1 << (N/2)];//表示的是第一个堆枚举的可能的情况总数

bool cmp(Node a, Node b) {//排序函数,因为待会我们搜索的时候是按照W的大小进行二分
	if(a.w != b.w)
		return a.w < b.w;
	return a.v > b.v;
}

int erfen(int l,int r,ll k) {//二分搜索
	while(l + 1 < r) {
		int mid = l + r >> 1;
		if(ps[mid].w <= k) {
			l = mid;
		}
		else {
			r = mid;
		}
	}
//此时的r表示的是大于k的第一个位置
	return r - 1;
}

void slove() {
	int len1 = n / 2;
	for(int i = 0, len = 1 << len1; i < len; ++i) {//二进制枚举第一个堆可能的情况
		int tempw = 0, tempv = 0;
		for(int j = 0;j < len1; ++j) {
			if(i >> j & 1) {//是否选取
				tempw += w[j];
				tempv += v[j];
			}
		}
		ps[i] = (Node){tempw,tempv};
	}
	sort(ps,ps+(1<            
关注
打赏
1688896170
查看更多评论

暂无认证

  • 5浏览

    0关注

    115984博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

0.0335s