牛客12650题解析:基于贪心算法的桌子与客人匹配问题

一、题目解读
牛客12650题要求处理一个资源分配问题:给定n张不同容量的桌子与m个携带消费金额的客人,客人需匹配到可容纳人数的桌子,目标是最大化所有匹配客人的总消费金额。题目本质是约束条件下的优化问题,需平衡桌子容量与客人需求的匹配效率。
二、解题思路
1. 贪心策略核心:优先安排高消费金额的客人,确保“价值最大化”的匹配。
2. 数据结构选择:
桌子容量存入multiset(支持自动排序与快速查找),便于动态删除已占用桌子。
客人信息用vector存储,按消费金额降序排序,确保优先处理高价值客人。
3. 关键操作:通过lower_bound定位首个满足容量要求的桌子,实现O(logn)查找效率,避免暴力遍历。
三、解题步骤
1. 输入处理:
读取桌子容量并存入multiset,自动升序排列。
读取客人信息(人数与消费金额),存入vector后排序(金额降序)。
2. 匹配逻辑:
遍历客人列表,对每个客人调用tables.lower_bound(人数)查找合适桌子。
若找到桌子,累加消费金额并删除该桌子(避免重复使用)。
3. 输出结果:最终累计的消费总额即为最优解。
四、代码与注释
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
// 客人结构体(按消费金额降序排序)
struct Guest {
int b; // 人数
int c; // 消费金额
bool operator<(const Guest& other) const {
return c > other.c; // 自定义排序规则:金额降序
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); // 加速输入
int n, m; // 桌子数量、客人数量
cin >> n >> m;
// 桌子容量存入multiset(自动排序)
multiset<int> tables;
for (int i = 0; i < n; ++i) {
int a;
cin >> a;
tables.insert(a);
}
// 客人信息读取与排序
vector<Guest> guests(m);
for (int i = 0; i < m; ++i) {
cin >> guests[i].b >> guests[i].c;
}
sort(guests.begin(), guests.end()); // 按消费金额降序排列
long long total = 0; // 累计消费金额
for (const auto& guest : guests) {
// 查找首个满足人数的桌子(O(logn))
auto it = tables.lower_bound(guest.b);
if (it!= tables.end()) {
total += guest.c;
tables.erase(it); // 删除已占用桌子
}
}
cout << total << endl;
return 0;
}五、总结
本解法通过“贪心+数据结构优化”实现高效解题:
● 排序与lower_bound的结合避免了复杂匹配搜索,时间复杂度O(mlogn)。
● 动态删除占用桌子确保解的唯一性,符合题目约束。
● 代码结构清晰,注释明确,适用于算法面试与工程实践。
原创内容 转载请注明出处






