题目大意:使尽可能多的物品放入背包使得价值之和最大
思路解析:本题实际上是一道二进制相关的题目。因重量需要按位或运算,我们将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;
}