H.01背包,但是bit(2024牛客寒假训练营)

题目大意:使尽可能多的物品放入背包使得价值之和最大

思路解析:本题实际上是一道二进制相关的题目。因重量需要按位或运算,我们将m转化为二进制来看,要想背包放的物品尽可能多,那么m转化为二进制后1的个数应尽可能多。所以我们可以按照m分类出很多背包m'使得m'<=m,然后枚举每一个m'求其总价值,然后所有总价值取最大值,举一个简单例子:

m=21->(10101)

m'可以为:

10101->21

10011->19

01111->15

废话不多说,代码如下:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using T = pair<int, int>;
//set<int>S;
//unordered_map<int, int>mp;
const int N = 2e5 + 10;
int a[N];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	int t; cin >> t;
	while (t--) {
		int n, m;
		cin >> n >> m;
		vector<int>v1;
		vector<T>val;
		int i;
		for (i = 1; i <= n; ++i) {
			int v, w;
			cin >> v >> w;
			val.push_back({ v,w });
		}
		if (m == 0) {
			ll ans{};
			for (i = 0; i < val.size(); ++i) {
				if (val[i].second == 0)ans += val[i].first;
			}
			cout << ans << endl;
			continue;
		}
		int t = m;
		int cnt = 0;
		while (t) {
			if (t == m) {
				v1.push_back(t);
			}
			else if (t & 1)v1.push_back(((t >> 1) << (cnt + 1)) + (1 << cnt) - 1);
			cnt++;
			t >>= 1;
		}int j;
		//for (i = 0; i < v1.size(); ++i)cout << v1[i] << " ";
		ll res{};
		for(i=0;i<v1.size();++i){
			ll ans{};
			for (j = 0; j < val.size(); ++j) {
				if ((val[j].second | v1[i]) <= m)ans += val[j].first;
			}
			res = max(res, ans);
		}
		cout << res << endl;
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值