题目
贪心,排序
思路
这是一道贪心题,该怎么贪心是我们要考虑的问题。
由于要使所获得的利润最大,并且给定的机器是固定的(资源固定),所以应该优先选择能得到利润最多的任务来做,如果有多台机器都能完成该任务,则应该选择最长工作时间最短并且等级最低(最适合)的机器来完成该任务。
由于题目所给的利润计算公式中时间占比大于难度等级占比,所以应该优先考虑时间满足,再考虑等级满足,应该先将任务和机器都从大到小排序,如果时间一样则等级从大到小,如果时间不一样则按时间从大到小。
排好序之后我们遍历每一个任务,并将时间上能完成该任务的所有机器都丢到一个有序集合中,然后从这个集合中找出等级最小且能满足任务的机器,将任务个数和答案更新,并将该机器从有序集合中去掉
由于是从大到小排好序的,所以之后的任务一定能被之前的机器在时间上满足。
代码
#include <algorithm>
#include <iostream>
#include <set>
#include <vector>
using namespace std;
using LL = long long;
using PII = pair<int, int>;
bool cmp(const PII& a, const PII& b) {
if (a.first == b.first) return a.second > b.second;
return a.first > b.first;
}
int main(void) {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n = 0, m = 0;
cin >> n >> m;
vector<PII> a(n), b(m);
multiset<int> st;
int i = 0;
for (i = 0; i < n; i++) {
cin >> a[i].first >> a[i].second;
}
for (i = 0; i < m; i++) {
cin >> b[i].first >> b[i].second;
}
sort(a.begin(), a.end(), cmp);
sort(b.begin(), b.end(), cmp);
int j = 0, k = 0;
LL ans = 0;
multiset<int>::const_iterator pos;
for (i = 0; i < m; i++) {
// 选择时间上满足的机器
while (j < n && a[j].first >= b[i].first) {
st.emplace(a[j].second);
j++;
}
// 寻找能满足任务的等级最低的机器
if ((pos = st.lower_bound(b[i].second)) != st.end()) {
k++;
ans += 500 * b[i].first + 2 * b[i].second;
st.erase(pos);
}
}
cout << k << " " << ans << endl;
return 0;
}