当日总结

链接: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;

}

posted @ 2025-09-24 23:52  lagranSun  阅读(11)  评论(0)    收藏  举报