hdu4864 贪心

题意:    

   给你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;
}
      

原文地址:https://www.cnblogs.com/csnd/p/12062933.html