任务(贪心)
今天公司有 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
*/

浙公网安备 33010602011771号