题意:
给你n太机器,m个任务,每个任务和机器都有两个权值x,y,每个机器只能被一个任务使用,条件是机器的两个权值分别比任务的大于等于,每个任务获得的价值是x*500+y*2,问你最多能完成多少任务,在完成任务最多的条件下,最多能获得多少价值。
思路:
一开始没想到是贪心,我读完题第一感觉就是费用流啊!后来一看数据,费用流不行(如果数据小点费用流果断能简单处理),后来别人说是贪心,我很不理解,贪心如果只是求最大的个数我可以求,也可以理解,但怎么保证最大价值呢?蛋疼,怪我没有注意那个公式v = x*500 + y * 2 哎!,sb了,人家不可能随便给你个式子啊,y的范围是<=100的,也就是说y怎么样也没有x变化1价值增加的多,所以我们要优先保护x,所以在二级排序的时候先以x,在y,这样就可以在保证个数最大的情况下价值最大了,整个过程还是简单贪心,排
序的条件是这样的
return a.x>b.x || a.x==b.x&&a.y>b.y || a.x==b.x && a.y==b.y &&a.v>b.v
v是我自己虚拟出来的,机器是1,任务是0,为了吧机器放在前面
然后for循环处理,从大到小,每个任务都要被他前面的机器中能处理他中y最小的那个处理。更新到最后就行了。
#include<stdio.h> #include<string.h> #include<algorithm> #include<set> using namespace std; typedef struct { int x ,y ,v; }NODE; NODE node[220000]; set<int>my_set; int set_num[105]; bool camp(NODE a ,NODE b) { return a.x > b.x || a.x == b.x && a.y > b.y || a.x == b.x && a.y == b.y && a.v > b.v; } int main () { int n ,m ,i ; __int64 ans1 ,ans2; while(~scanf("%d %d" ,&n ,&m)) { for(i = 1 ;i <= n ;i ++) { scanf("%d %d" ,&node[i].x ,&node[i].y); node[i].v = 1; } for(i = 1 ;i <= m ;i ++) { scanf("%d %d" ,&node[i+n].x ,&node[i+n].y); node[i+n].v = 0; } sort(node + 1 ,node + n + m + 1 ,camp); my_set.clear(); my_set.insert(1050); memset(set_num ,0 ,sizeof(set_num)); for(ans1 = ans2 = 0 ,i = 1 ;i <= n + m ;i ++) { if(node[i].v) { my_set.insert(node[i].y); set_num[node[i].y] ++; } else { int now = *my_set.lower_bound(node[i].y); if(now != 1050) { ans1 += (__int64)(node[i].x * 500) + (__int64)(2 * node[i].y); ans2 ++; if(!(--set_num[now])) my_set.erase(now); } } } printf("%I64d %I64d " ,ans2 ,ans1); } return 0; }