hdu4864 hdu4268 贪心 lower_bound
hdu4864
题意:
有n个机器,m个任务,n,m<=100000,每个机器都有工作时间的最大限制xi(0<xi<1440)和完成的最大难度yi(0<=yi<=100),每个任务也有所需要的时间和难度,只要机器的时间大于等于任务,难度大于等于任务,该任务就可以被机器完成,每完成一个任务就可以得到500*xi+2*yi的money,问最多能有多少个任务被完成,并且保证完成任务数量最多的情况下,所得到的money最多是多少?
思路:
由于money是500*x+2*y,而y最大是100,则只要保证任务的x最大,那么得到的钱一定是最多的。
将任务按照时间x从大到小排序,然后依次用任务查找机器,时间x从大到小保证了得到的钱是最多的,然后每个任务找出大于该任务难度y且与难度y最接近的机器完成该任务。现在有个问题需要证明一下,每次找难度最接近的机器,那么时间x只是大于任务x即可,时间是否物尽其用了呢?是否有浪费呢?不会,因为任务的x是从大到小排序遍历,如果任务找到了一个大于自身时间x的机器,就用,即使有别的x更大的机器没有被用,但是可以留下来给别的任务用。
比赛的时候代码WA,虽然也是贪心,但是用的机器查找任务,导致x做到了物尽其用,y并没有做到,so WA~
不要迷迷糊糊的写,要严谨的证明全对再下手写~
1 /*=============================================================== 2 * Copyright (C) 2014 All rights reserved. 3 * 4 * File Name: hdu4864.cpp 5 * Author:sunshine 6 * Created Time: 2014年07月23日 7 * 8 ================================================================*/ 9 #include <map> 10 #include <set> 11 #include <queue> 12 #include <stack> 13 #include <math.h> 14 #include <stdio.h> 15 #include <string.h> 16 #include <iostream> 17 #include <algorithm> 18 19 using namespace std; 20 21 #define N 100005 22 23 struct node{ 24 int x,y; 25 bool operator < (const node &n1) const{ 26 if(x != n1.x) return x > n1.x; 27 return y > n1.y; 28 } 29 }task[N]; 30 31 int main(){ 32 int n,m; 33 int x,y; 34 while(cin >> n >> m){ 35 36 multiset<int> S[105]; 37 long long res = 0; 38 int cnt = 0; 39 40 for(int i = 0;i < n;i ++){ 41 scanf("%d%d", &x, &y); 42 S[y].insert(x); 43 } 44 45 for(int i = 0;i < m;i ++){ 46 scanf("%d%d", &task[i].x, &task[i].y); 47 } 48 49 sort(task,task+m); 50 51 for(int i = 0;i < m ;i ++){ 52 x = task[i].x; 53 y = task[i].y; 54 55 for(int j = y;j <= 100;j ++){ 56 if(S[j].empty()) { 57 continue; 58 } 59 60 multiset<int>::iterator it = S[j].lower_bound(x); 61 62 if(it == S[j].end() || *it < x){ 63 continue; 64 }else{ 65 cnt ++; 66 res += 500 * x + 2 * y; 67 S[j].erase(it); 68 break; 69 } 70 } 71 } 72 printf("%d %I64d\n",cnt,res); 73 } 74 return 0; 75 }
hdu4268
题意:
Alice有n个纸片,Bob有n个纸片,n<=100000每个纸片有长度和宽度,已知这2*n个纸片的长和宽,求Alice最多能覆盖Bob多少张纸片,每张纸片只能被用一次。
思路:
将这2*n张纸片按照长x从大到小排序,y从大到小排序,如果x、y相等,则Alice的纸片排在前面,用Bob去查找Alice,即Alice所有的纸片插入到set中,但是并不是一下子全部插入到set中,而是边插入set处理边求解Bob的第i张纸片能否被覆盖,这样能够保证之前插入的所有纸片的长x都大于等于自身的x,每次遇到Alice的纸片则插入到set中,每次遇到Bob的纸片则在set中查找刚好大于等于y的第一个Alice的纸片,然后把它删除,依次。
1 /*=============================================================== 2 * Copyright (C) 2014 All rights reserved. 3 * 4 * File Name: hdu4268.cpp 5 * Author:sunshine 6 * Created Time: 2014年07月23日 7 * 8 ================================================================*/ 9 #include <map> 10 #include <set> 11 #include <queue> 12 #include <stack> 13 #include <math.h> 14 #include <stdio.h> 15 #include <string.h> 16 #include <iostream> 17 #include <algorithm> 18 19 using namespace std; 20 21 #define N 100010 22 23 struct node{ 24 int x,y; 25 bool id; 26 }p[2*N]; 27 28 int cmp(node n1,node n2){ 29 if(n1.x == n2.x && n2.y == n2.y) return n1.id > n2.id; 30 if(n1.x != n2.x) return n1.x > n2.x; 31 return n1.y > n2.y; 32 } 33 34 int main(){ 35 int cas; 36 int n; 37 int x,y; 38 scanf("%d", &cas); 39 while(cas --){ 40 scanf("%d", &n); 41 for(int i = 0;i < n;i ++){ 42 scanf("%d%d", &p[i].x, &p[i].y); 43 p[i].id = 1; 44 } 45 46 for(int i = n;i < 2 * n;i ++){ 47 scanf("%d%d", &p[i].x, &p[i].y); 48 p[i].id = 0; 49 } 50 51 sort(p,p + 2 * n,cmp); 52 multiset<int>S; 53 int cnt = 0; 54 for(int i = 0;i < 2 * n;i ++){ 55 if(p[i].id){ 56 S.insert(p[i].y); 57 }else{ 58 y = p[i].y; 59 multiset<int>::iterator it = S.lower_bound(y); 60 61 if(it == S.end() || *it < y){ 62 continue; 63 }else{ 64 S.erase(it); 65 cnt ++; 66 } 67 } 68 } 69 printf("%d\n",cnt); 70 } 71 return 0; 72 }