POJ - 3614 Sunscreen

题意:c头奶牛,每一头奶牛有一个忍耐区间 [ l , r ] [l, r] ,现在给出 l l 种忍耐值以及对应的数量,经过最优的分配,c头奶牛各获得一个忍耐值,问最多有多少头奶牛的忍耐值在其忍耐区间内?
思路
[ l 1 , r 1 ] [ l 2 , r 2 ] r [l_1,r_1][l_2,r_2](按照r递增排序后,相邻的区间)

情况一:
[ l 1 , l 2 , r 2 , r 1 ] [l_1,l_2,r_2,r_1]
我们考虑,假如有一个忍耐值位于这个区间内部
1、假定落在区间 [ l 2 , r 2 ] [l_2,r_2]
那我们贪心地想,把这个忍耐值给第二头奶牛更适宜
2、其余情况
只有一种奶牛符合条件,不需要贪心考虑

情况二:
[ l 1 , r 1 , l 2 , r 2 ] [l_1,r_1,l_2,r_2]
对于这种情况,忍耐值不管是什么,都最多只有一头奶牛符合
所以,不需要贪心考虑

情况三:
[ l 1 , l 2 , r 1 , r 2 ] [l_1,l_2,r_1,r_2]
1、忍耐值位于区间 [ l 2 , r 1 ] [l_2,r_1]
显然,按照贪心思路考虑,给第一头奶牛更适宜
2、其余情况
只有一头奶牛符合,不需要贪心

综合得知,我们每次把忍耐值给某个奶牛,这个奶牛的忍耐区间右端点与该忍耐值最接近

代码实现
1、忍耐区间按右端点递增排序
2、忍耐值递增排序
3、枚举忍耐值,从头到尾check每一个忍耐区间(保证与忍耐值最接近)

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn = 2500 + 5;
struct node{
 	 int l, r;
}a[maxn];
struct Node{
 	 int val, num;
}s[maxn];
int c, l; bool vis[maxn];
bool cmp(node b, node c){
 	 if(b.r == c.r) return b.l < c.l;
	 return b.r < c.r;
}
bool cmp1(Node b, Node c){
	 if(b.val == c.val) return b.num > c.num;
	 return b.val < c.val;
}
int main(){
	 scanf("%d%d", &c, &l);
 	 for(int i = 1; i <= c; i++){
 	 	scanf("%d%d", &a[i].l, &a[i].r);
 	 }
	 sort(a + 1, a + c + 1, cmp);
	 for(int i = 1; i <= l; i++){
  	 	scanf("%d%d", &s[i].val, &s[i].num);
 	 }
	 sort(s + 1, s + l + 1, cmp1);
 	 int ans = 0, j, num, val;
 	 for(int i = 1; i <= l; i++){
         	num = s[i].num; val = s[i].val;
  		for(j = 1; j <= c; j++){
   			if(num == 0) break;
   			if(!vis[j] && val >= a[j].l && val <= a[j].r){
	    			ans++;
	    			num--;
	    			vis[j] = true;
	   		}
 	 	}
 	}
 	printf("%d\n", ans);
 	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44412226/article/details/105139223