当日总结
链接:https://ac.nowcoder.com/acm/problem/268729
来源:牛客网
小苯有一个容量为
𝑘
k 的背包,现在有
𝑛
n 个物品,每个物品有一个体积
𝑣
v 和价值
𝑤
w,他想知道在体积不超过
𝑘
k 的前提下,他最多能装价值为多少的物品。
本问题中,物品的总体积定义为所装物品的体积的
&
&(按位与),总价值也定义为所装物品的价值的
&
&(按位与)。
(如果不选物品,则价值为 0,所占体积也为 0。)
输入描述:
输入包含
𝑛
+
1
n+1 行。
第一行两个正整数
𝑛
,
𝑘
(
1
≤
𝑛
≤
2
×
1
0
5
,
0
≤
𝑘
≤
1
0
9
)
n,k (1≤n≤2×10
5
,0≤k≤10
9
),分别表示物品个数和背包容量。
加下来
𝑛
n 行,每行两个正整数
𝑣
𝑖
,
𝑤
𝑖
(
0
≤
𝑣
𝑖
,
𝑤
𝑖
≤
1
0
9
)
v
i
,w
i
(0≤v
i
,w
i
≤10
9
),表示每个物品的体积和价值。
输出描述:
输出包含一行一个整数,表示能装的最大价值。
include
include
include <unordered_set>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, k;
cin >> n >> k;
vector<pair<int, int>> items(n);
for (int i = 0; i < n; ++i) {
cin >> items[i].first >> items[i].second;
}
int result = 0;
// 从最高位到最低位依次尝试
for (int bit = 30; bit >= 0; --bit) {
int candidate = result | (1 << bit);
vector<int> vs;
// 筛选符合条件的物品体积
for (auto& item : items) {
int v = item.first;
int w = item.second;
if ((w & candidate) == candidate) {
vs.push_back(v);
}
}
if (vs.empty()) continue;
// 检查是否存在非空子集的体积与运算结果 <= k
bool valid = false;
unordered_set<int> current;
for (int v : vs) {
if (v <= k) {
valid = true;
break;
}
unordered_set<int> temp;
temp.insert(v);
for (int x : current) {
int val = x & v;
if (val <= k) {
valid = true;
break;
}
temp.insert(val);
}
if (valid) break;
// 合并到current集合
for (int x : temp) {
current.insert(x);
}
}
if (valid) {
result = candidate;
}
}
cout << result << endl;
return 0;
}

浙公网安备 33010602011771号