存在 n种物品,第i种的体积为 ai ,数量有 bi 个。 一旦有 2^k 个物品的体积均为v,则将它们合成为一个体积为 2^k*v的物品( k>=1)。 容易知道,无论用何种方式合并,最终所剩物品数量是确定的。 求最后剩下多少个物品。c++完整代码
时间: 2024-10-04 17:00:55 浏览: 40
这个问题可以用哈希表和优先队列(堆)的数据结构来解决,因为我们需要频繁地对物品进行合并操作,而堆恰好能保持每次合并体积最大的物品。以下是C++的一个解决方案:
```cpp
#include <vector>
#include <unordered_map>
#include <queue>
using namespace std;
int merge(vector<int>& a, vector<int>& b, unordered_map<int, int>& cnt) {
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq; // 优先队列用于存放物品
for (int v : a) {
if (cnt[v]) {
pq.push({-v, cnt[v]}); // 用负值表示体积,便于比较
}
}
for (int v : b) {
if (cnt[v]) {
pq.push({-v, cnt[v]});
}
}
int res = 0;
while (!pq.empty()) {
pair<int, int> item = pq.top();
pq.pop();
int volume = -item.first;
int numItems = item.second;
res += numItems;
if (volume > 1) {
cnt[2 * volume] += numItems; // 合并
} else {
break; // 只有单个物品时停止
}
}
return res;
}
int mergeItems(vector<int>& a, vector<int>& b) {
unordered_map<int, int> cnt;
for (auto &i : a) {
cnt[i]++;
}
for (auto &i : b) {
cnt[i]++;
}
int totalItems = a.size() + b.size();
for (int i = 1; i <= totalItems; i *= 2) {
cnt[i] += cnt[i / 2]; // 预处理所有可能的合并结果
}
return cnt[totalItems];
}
int main() {
vector<int> a = {1, 2, 4}; // 物品a的体积列表
vector<int> b = {1, 2, 8}; // 物品b的体积列表
cout << "最终剩下 " << mergeItems(a, b) << " 个物品.\n";
return 0;
}
```
在这个代码中,`mergeItems`函数负责合并两个物品集,`merge`函数则用于合并具体的物品集合。通过预处理所有可能的合并结果,我们可以减少实际的合并操作次数,提高了算法效率。
阅读全文