任务(贪心)
今天公司有 m 项任务要完成。第 i 项任务需要 x[i] 分钟来完成。同时,这个任务有一个困难级别 y[i]。级别低于该任务级别 y[i] 的机器无法完成这项任务。如果公司完成了这项任务,他们将获得 (500* x[i]+2* y[i]) 美元。
公司有 n 台机器。每台机器都有最大工作时间和一个级别。如果任务的时间超过机器的最大工作时间,则该机器无法完成这个任务。每台机器一天只能完成一项任务。每项任务只能由一台机器完成。
公司希望最大化今天他们可以完成的任务数量。如果存在多个解决方案,他们希望使收益最大化。
输入格式
第一行包含两个整数 N 和 M。N 是机器的数量。M 是任务的数量 (1 <= N <= 100000, 1<= M<= 100000)。
接下来的 N 行每行包含两个整数 x[i](0<x[i]<1440),y[i](0<= y[i]<= 100)。x[i] 是机器可以工作的最长时间。y[i] 是机器的级别。
接下来的 M 行每行包含两个整数 x[i](0<x[i]<1440),y[i](0<= y[i]<= 100)。x[i] 是完成任务所需的时间。y[i] 是任务的级别。
输出格式
对于每个测试用例,输出两个整数,分别是公司今天可以完成的最大任务数量和他们将获得的收益。
输入/输出例子1
输入:
1 2
100 3
100 2
100 1
输出:
1 50004
样例解释
无
贪心的值关于多个时,关注最重要的值,根据最重要的值贪心!
洛谷题解:https://www.luogu.com.cn/article/uh7z6p19
这是一道贪心好题。
可以看到这题中的关键变量有很多,但是要抓住其中一个最重要的,根据题目中的计算公式发现,时间才是最重要的(乘了500,等级撑死都打不过时间的贡献)
这是第一眼应该想到的,然后这种题要排个序,第一关键词当然是时间,然后考虑等级,因为贪心,还是比较容易想到的
排序完之后,我们根据每个任务来确定完成这个任务的机器,首先要看时间符不符合,由于任务时间是递减的,所以可以把符合的时间加入集合,并进一步判断
然后我们考虑找第一个大于等于这个任务等级的机器等级,毕竟集合内时间都是满足的,只用考虑等级,然而都有符合的了,肯定用一个最小的等级,留着大等级以后用,有一部分贪心思想
所以考虑用集合
#include <bits/stdc++.h> using namespace std; const int N=1e5+5; struct node { long long x, y; }a[N], b[N]; int n, m, h=0; long long ans=0, cnt=0; multiset<int> s; multiset<int>::iterator it; bool cmp(node a, node b) { if (a.x==b.x) return a.y>b.y; return a.x>b.x; } int main() { scanf("%d%d", &n, &m); for (int i=1; i<=n; i++) scanf("%lld%lld", &a[i].x, &a[i].y); for (int i=1; i<=m; i++) scanf("%lld%lld", &b[i].x, &b[i].y); sort(a+1, a+1+n, cmp); sort(b+1, b+1+m, cmp); h=1; for (int i=1; i<=m; i++) { for (int j=h; j<=n; j++) { if (a[j].x>=b[i].x) { s.insert(a[j].y); if (j==n) h=j+1; //记得别漏判了,如果机器最后一台也符合,加入完后一定要更新记录完毕的下标值!! } else { h=j; break; } } it=s.lower_bound(b[i].y); if ((it)!=(s.end())) { cnt++; ans+=500*b[i].x+2*b[i].y; s.erase(it); } } printf("%lld %lld", cnt, ans); return 0; } /* 3 2 98 1 99 5 100 1 99 5 100 1 3 2 100 1 99 5 98 1 100 1 99 5 */