今天某公司有M个任务需要完成。
每个任务都有相应的难度级别和完成任务所需时间。
第i个任务的难度级别为yi,完成任务所需时间为xi分钟。
如果公司完成此任务,他们将获得(500 * xi + 2 * yi)美元收入。
该公司有N台机器,每台机器都有最长工作时间和级别。
如果任务所需时间超过机器的最长工作时间,则机器无法完成此任务。
如果任务难度级别超过机器的级别,则机器无法完成次任务。
每台机器一天内只能完成一项任务。
每个任务只能由一台机器完成。
请为他们设计一个任务分配方案,使得该公司能够最大化他们今天可以完成的任务数量。
如果有多种解决方案,他们希望选取赚取利润最高的那种。
输入格式
输入包含几个测试用例。
对于每个测试用例,第一行包含两个整数N和M,分别代表机器数量和任务数量。
接下来N行,每行包含两个整数xi,yi,分别代表机器最长工作时间和机器级别。
再接下来M行,每行包含两个整数xi,yi,分别代表完成任务所需时间和任务难度级别。
输出格式
对于每个测试用例,输出两个整数,代表公司今天可以完成的最大任务数以及他们将获得的收入。
数据范围
1≤N,M≤100000 ,
0<xi<1440,
0≤yi≤100
输入样例:
1 2
100 3
100 2
100 1
输出样例:
1 50004
思路:
刚开始看到这道题,觉得这是一个贪心,然后两个数字一组,很自然考虑到用pair去写,
那么问题,怎么贪?
通过要求的最大收入的表达是来看,x,y两个数,500*x + 2 y;看数据范围,y < 100; 2 * y < 200;
这个比500x 要小,因此我们根据x来贪。
先输入,再根据时间从小到大排序;然后倒着做(贪心这么贪),把任务放在循环里,因为任务要做,机器可以有不用的,一个机器一天完成一个,先做任务时间长的,然后把这个>=这个时间的机器找出来,所有的都要找出来,然后再根据任务难度选择最合适的机器,然后任务数++,花费+=;同时把这个机器删除。
这个题输出的时候,犯了一个很低级的错误,我把输出放到循环里面了,最后给了我三个输出。额呃呃呃来表达一下我的心情
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
using namespace std;
const int maxn = 1e5 + 10;
typedef pair<int,int> PII;
PII a[maxn],b[maxn];
int N,M,x,y;
multiset<int> s;
int main()
{
//机器数量和任务数量和任务数量
while(scanf("%d%d",&N,&M)!=EOF)
{
for(int i = 1; i <= N; i++)
//机器最长的工作时间和机器级别
scanf("%d%d",&a[i].first,&a[i].second);
for(int j = 1; j <= M; j++)
//完成任务所需要的时间和难度
scanf("%d%d",&b[j].first,&b[j].second);
//排序,从小到大
sort(a+1,a+N+1);
sort(b+1,b+M+1);
s.clear();
//任务数量
int cnt = 0;
//收入
long long ans = 0;
//把所有的任务按照时间排列,i表示任务,j表示机器
for(int i = M,j = N;i>=1; i--)
{
//任务的时间要比机器的时间短,即<=;还要考虑难度,因此把所有的都找出来,这时候找的是机器
while(j >= 1 && b[i].first <= a[j].first)
s.insert(a[j--].second);
//先把大的数字放进去,set是从小到大排的,lower_bound找到的是第一个大于等于b[i].second的,
auto it = s.lower_bound(b[i].second);
if(it != s.end()){
cnt++;
ans += 500*b[i].first + 2 * b[i].second;
//删除,找到it,删除这个机器,剩下的放在里面
s.erase(it);
}
}
printf("%d %lld",cnt,ans);
}
return 0;
}
补充:pair默认的两个first,second;
multiset允许重复,具有自动排序
遍历
set元素唯一,默认升序
遍历:
set<int> s;
for(auto it : s)
cout << it;