原题HDU4864
Sample Input
1 2
100 3
100 2
100 1
Sample Output
1 50004
题目大意
条件:
Task xi,yi
Machine xj,yj
只有xj>xi&&yj>yi task才可以被执行
收益:500*xi+2*yi
求解:
输出多可以被解决的task和最多的收益
解题-贪心
收益最大
主要考虑x(对收益影响大)
收益由被解决的task决定
task按照x从大到小排序(相同按照y),越前task收益越大,从前往后解决的task越多,收益越大。
? 收益最大状态<=>task解决最多状态?
为什么这么贪心,因为若还存在任务(xk,yk)使得这个机器能被使用,但xj>=xk,所以获得金钱更多,优先选择j;若k不能使用这个机器,那么必定也就不存在其他机器能被使用,除非是新加入的机器,但新加入的必定不能完成任务j,所以完成任务保证了最多。
https://blog.csdn.net/a601025382s/article/details/38046927
解决最多
主要考虑y(对收益影响没有x大,但是限制解决个数,x优先排序已经解决)
寻找可以解决当前task的machine(此时收益已定)
选择y最小的machine(留大的解决更多问题)
tips
因为是按照x优先排序的,所以可以解决之前task的machine,x一定满足解决之后task。
与HDU4268类似
变量-伪代码
#define N 100005
struct node{
intx,y;
}task[N],machine[N];
#include< set >
multiset< int > myset;
multiset< int > :: iterator it;
int n,m;
int cnt;
long long sum; printf(“%I64d”,sum);
输入 n,m,task[],machine[]
sort()task[],machine[]从大到小
遍历task[i]
当(找到了x满足的machine)
存放y在myset
继续找j++;
如果有x满足的话
找第一个>=task[i].y的machine.y//lower_bound()
找到了的话//没找到!it=myset.end()越界
cnt++;算sum;
删除这个machine.y(保留其他machine.y)
输出cnt sum
AC代码
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#include<set>
#define N 100005
#define LL long long
using namespace std;
struct node{
int x,y;
}task[N],machine[N];
multiset<int> myset;
multiset<int>::iterator it;
bool cmp(node n1,node n2){
if(n1.x==n2.x)
return n1.y>n2.y;
return n1.x>n2.x;
}
int main(){
ios::sync_with_stdio(false);
int i,j;
int n,m;
int cnt;
LL sum;
while(cin>>n>>m){
cnt=sum=0;myset.clear();
for(i=0;i<n;i++)
cin>>machine[i].x>>machine[i].y;
for(i=0;i<m;i++)
cin>>task[i].x>>task[i].y;
sort(machine,machine+n,cmp);
sort(task,task+m,cmp);
j=0;
for(i=0;i<m;i++){
while(j<n&&machine[j].x>=task[i].x){
myset.insert(machine[j].y);
j++;
}
if(myset.size()){
it=myset.lower_bound(task[i].y);
if(it!=myset.end()){
cnt++;sum+=500*task[i].x+2*task[i].y;
myset.erase(it);
}
}
}
printf("%d %I64d\n",cnt,sum);
}
return 0;
}